Per farla breve, non c'è nessuna soluzione qui che piace a tutti.
Considerate questo idioma comune:
var customer = GetCustomer(...); // of type 'Customer'
var address = customer && customer.address;
if(address) {
printAddressLabel(address); // Signature: (Address) => void
} else {
// Couldn't find the customer or the customer has no address on file
}
Sarebbe piuttosto inconsistente a rinunciare e decidere che 'indirizzo' è 'qualsiasi' perché non c'è miglior tipo comune tra il Cliente e Indirizzo.
Nella maggior parte dei casi in cui viene utilizzato l'operatore &&, sia i tipi già corrispondono o && viene utilizzato in maniera valore coalescenti come sopra. In entrambi i casi, il ritorno il tipo di l'operando di destra dà all'utente del tipo previsto.
Mentre la sicurezza tipo è tecnicamente abbattere, a questo punto, non è farlo in un modo che è suscettibile di provocare un errore. O si sta andando a testare il valore risultante per truthiness (nel qual caso il tipo è più o meno irrilevante), o avete intenzione di utilizzare l'operando presuntiva giusta per alcune operazioni (nell'esempio sopra fare entrambe).
Se guardiamo gli esempi che hai elencato e facciamo finta l'operando di sinistra è indeterminato truthy o falsy e quindi provare a scrivere il codice sano di mente che avrebbe operare sul valore di ritorno, diventa molto più chiaro - non c'è solo tanto si può fare con la 'false && {}' che non sia già in corso in una 'qualsiasi' posizione di discussione o di prova truthiness.
appendice
Dal momento che alcune persone non sono stati convinti da quanto sopra, ecco una spiegazione diversa.
Facciamo finta per un momento che il sistema di tipo dattiloscritto ha aggiunto tre nuovi tipi: Truthy<T>, Falsy<T>, e Maybe<T>, che rappresentano possibili valori truthy / falsy di tipo T. Le regole per questi tipi sono i seguenti:
Truthy<T> si comporta esattamente come T
- Non è possibile accedere a qualsiasi proprietà di
Falsy<T>
- Un'espressione del tipo
Maybe<T>, se usati come la condizione in un ifblocco, diventa Truthy<T>nel corpo dello stesso ifblocco e Falsy<T>in elseblocco
Questo avrebbe permesso di fare le cose in questo modo:
function fn(x: Maybe<Customer>) {
if(x) {
console.log(x.address); // OK
} else {
console.log(x.phone); // Error: x is definitely falsy
}
console.log(x.name); // Warning: x might be falsy!
}
Abbastanza bene finora. Ora siamo in grado di capire quali sono le regole di tipo sono per l'operatore &&.
Truthy<T> && x dovrebbe essere un errore - Se il lato sinistro è noto per essere truthy, si dovrebbe avere appena scritto x
Falsy<T> && xdovrebbe essere un errore - se il lato sinistro è noto per essere falsy, xè codice irraggiungibile
Maybe<T> && x dovrebbe produrre ... che cosa?
Sappiamo che il risultato di Maybe<T> && xsarà un valore falsy di tipo To x. Esso non può produrre Truthy<T>(a meno che T== il tipo di xnel qual caso questa intera discussione è discutibile). Chiamiamo questo nuovo tipo Falsy<T> XOR Maybe<U>.
Quali dovrebbero essere le regole di Falsy<T> XOR Maybe<U>essere?
- Chiaramente, non è possibile utilizzare le proprietà di
Tsu di esso. Se il valore è di tipo T, è falsy, e non sicuro per l'uso.
- Si dovrebbe essere in grado di usarlo come
Maybe<U>, dal momento che Falsy<T>e Falsy<U>hanno gli stessi comportamenti
- Non si dovrebbe essere in grado di utilizzare le proprietà di
U, perché il valore potrebbe essere ancora falsy.
- Se lo si utilizza in una
ifprova, allora dovrebbe diventare Truthy<U>nel blocco di quella ifdichiarazione
In altre parole, Falsy<T> XOR Maybe<U> è Maybe<U> . Segue tutte le stesse regole. Non è necessario complicare il sistema di tipo affatto qui aggiungendo questo strano XORtipo, perché un tipo che si adatta a tutte le specifiche è necessario esiste già.
Questo è un po 'come dare a qualcuno una scatola e dire "Questo è sia una scatola vuota di spazzatura, o di una scatola piena di materiali riciclabili". È possibile svuotare in modo sicuro il contenuto della scatola nel cestino.