Para resumir, no hay ninguna solución a este problema que agrada a todos.
Considere este lenguaje común:
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
}
Sería bastante cojo a renunciar y decidir que 'dirección' es 'cualquiera' porque no hay mejor tipo común entre el Cliente y Dirección.
En la mayoría de los casos en que se utiliza el operador &&, ya sea los tipos ya coinciden, o && está siendo utilizado de manera coalescente valor como anteriormente. En cualquier caso, volviendo el tipo del operando derecho le da al usuario el tipo esperado.
Mientras que la seguridad de tipos es técnicamente rompiendo en este punto, no es hacerlo de una manera que es probable que resulte en un error. Ya sea que vas a probar el valor resultante de truthiness (en cuyo caso el tipo es más o menos irrelevante), o vas a usar el operando presuntiva adecuado para alguna operación (el ejemplo anterior haciendo ambas cosas).
Si nos fijamos en los ejemplos que enumeró y pretender que el operando de la izquierda es indeterminada Truthy o Falsy y luego tratar de escribir código cuerdo que operaría en el valor de retorno, se hace mucho más claro - no es sólo la cantidad que puede hacer con la 'falsa && {}' que aún no está entrando en una 'cualquier' posición de argumento o prueba truthiness.
Apéndice
Ya que algunas personas no estaban convencidos de lo anterior, he aquí una explicación diferente.
Vamos a suponer por un momento que el sistema de tipos mecanografiado agregó tres nuevos tipos: Truthy<T>, Falsy<T>y Maybe<T>, en representación de los valores posibles Truthy / Falsy de tipo T. Las reglas para estos tipos son los siguientes:
Truthy<T> se comporta exactamente igual T
- No se puede acceder a las propiedades de
Falsy<T>
- Una expresión de tipo
Maybe<T>, cuando se utiliza como la condición en un ifbloque, se convierte en una Truthy<T>en el cuerpo de ese mismo ifbloque y una Falsy<T>en el elsebloque
Esto permitirá hacer cosas como esta:
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!
}
Bastante bueno hasta ahora. Ahora podemos averiguar cuáles son las reglas de tipos son para el operador &&.
Truthy<T> && x debe ser un error - Si el lado izquierdo es conocido por ser Truthy, debe acaba de escribir x
Falsy<T> && xdebe ser un error - Si el lado izquierdo es conocido por ser Falsy, xes código inalcanzable
Maybe<T> && x debe producir ... ¿qué?
Sabemos que el resultado de la Maybe<T> && xserá o bien un valor Falsy de tipo T, o x. No se puede producir Truthy<T>(a menos que T== del tipo de xen cuyo caso toda esta discusión es discutible). Vamos a llamar a este nuevo tipo Falsy<T> XOR Maybe<U>.
¿Qué deben las reglas de Falsy<T> XOR Maybe<U>ser?
- Claramente, no se puede utilizar las propiedades de
Tsobre ella. Si el valor es de tipo T, es Falsy, y no es seguro para su uso.
- Usted debe ser capaz de utilizarlo como
Maybe<U>, desde Falsy<T>y Falsy<U>tienen el mismo comportamiento
- No debería ser capaz de utilizar las propiedades de
U, ya que el valor aún podría ser Falsy.
- Si lo usa en una
ifprueba, entonces debe convertirse en una Truthy<U>en el bloque de esa ifdeclaración
En otras palabras, Falsy<T> XOR Maybe<U> es Maybe<U> . De ello se sigue todas las mismas reglas. No es necesario complicar el sistema de tipos a todos aquí por la adición de este raro XORtipo, debido a un tipo que se adapte a todas las especificaciones que necesita ya existe.
Esto es un poco como darle a alguien una caja y decir "esto es ya sea una caja vacía de la basura, o una caja llena de materiales reciclables". Puede vaciar de forma segura el contenido de la caja en la papelera de reciclaje.