¿Por qué se pierde el tipo fuerte con `any` en TypeScript?
¿Alguien puede explicar por qué el siguiente TypeScript no puede detectar el problema de tipos?
function z(a: number) {
console.log(a*a);
}
z(1); // works
z("xyz"); // fails type checking
function y(a: any){
z(a); // I expect this statement to be erroneous
}
y(1); // works
y("xyz"); // does not fail type checking; feels like duck-typing?
En el ejemplo anterior, el compilador sabe que a y se le está pasando un string y, por lo tanto, a z se le está pasando un string. Esto debería ser suficiente para un error del transpiler. ¿Alguien podría explicar las decisiones que se tomaron en el diseño del transpiler?
¡Gracias! :)
Respuesta #1
En y, a puede tener cualquier forma, por lo que es un number válido, any es un objeto muy permisivo, pero en el caso en que quieras decir, no sé qué es a, por lo tanto, podría querer realizar algunas verificaciones antes de llamar a z, entonces deberías usar unknown como el tipo menos permisivo.
function y(a: unknown){
z(a); // Argument of type 'unknown' is not assignable to parameter of type 'number'.ts(2345)
if (typeof a === 'number') {
z(a) // all good
}
}
any está ahí por compatibilidad con el código JavaScript existente o para eludir la seguridad, a partir de TypeScript 3.0 unknown es el tipo a usar cuando no estamos seguros de con qué tipo estamos tratando, obligando a primero acotar el tipo. https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type
Respuesta #2
¿Alguien puede explicar por qué el siguiente TypeScript no puede detectar el problema de tipos?
y("xyz"); // does not fail type checking; feels like duck-typing?
Ok, entonces ¿cuál es la firma del método y?
function y(a: any)
¿Es "xyz" un any válido? Sí lo es. Dicho esto, a ahora es de tipo any, no de tipo string. Has dicho explícitamente al compilador que es any, no string, así que dado que any podría ser un number, la llamada es válida.
En este sentido, el equipo de TypeScript simplemente decidió no hacer ninguna verificación de tipos en any porque JavaScript permite este tipo de comportamiento y el equipo de TypeScript quería extender/mejorar JavaScript, no impedirte hacer algo si querías. any es una característica opcional y puedes desactivar implicitAny usando los argumentos del compilador de TypeScript (o tsconfig.json).
