TypeScript es un lenguaje de programación fuertemente tipado y uno de los objetivos del sistema de tipos es hacer explícito la intención de código, con la finalidad de crear un código más robusto y consistente, pero si no usamos el sistemas de tipos adecuadamente podemos volver a caer el mismo infierno de JavaScript, siendo el tipo any
uno de los más peligrosos si se usa sin una razón válida.
A una variable de tipo any
se le puede asignar cualquier cosa, esto elimina las restricción de tipos, veamos algunos casos:
Caso 1
La variable country
puede ser de cualquier tipo, string
, number
, boolean
, etc, no es una variable fiable
let country: any = 'Perú'; // string country = 1; // number country = false; // boolean
Si usáramos un tipo definido, como por ejemplo country: string
TypeScript nos alertaría con un mensaje, el cual diría algo parecido a esto, «El tipo ‘string’ no se puede asignar al tipo ‘number'». y no transpilaria el código hasta solventar el problema.
Caso 2
Usar any
como tipo para los parámetros de una función (en este caso una función de suma), permitiría pasar cualquier cosa como parámetro, y en vez de sumar haría concatenaciones y estaríamos en la misma condición como si lo hicieras con JavaScript, ¡sin ninguna seguridad!
function sum(a: any, b: any) { return a + b } console.log(sum("Hello ", "World")) // "Hello World" console.log(sum("Hello ",{a:10})) // "Hello Object Object"
Caso 3
Definir un objeto como any
nos da la libertad de acceder a cualquier atributo del objeto, ¡así no exista!
const book: any = { author: "author name", issn: "issn value" }; console.log(book.doi) // undefined
Y así podríamos seguir, con muchos más ejemplos, de lo perjudicial que puede ser any
, ¿pero qué tipo de datos podemos usar si no sabemos el tipo?, la respuesta es: unknown
.
Si no conoce el valor de una variable, objeto, parámetro, etc, en el 99 % de los casos debería usar
unknown
en vez deany
.
Unknown
Usar unknown
nos permite trabajar con valores desconocidos con la seguridad de tipos , las dos principales características de unknown
son:
- No permite que una variable definida como
unknown
pueda ser asignada a otra, evitando así la propagación de datos inconsistentes.
let x:unknown = 10; let v1: number = x // Error let v2: object = x; // Error let v3: string = x; // Error let v4: string[] = x; // Error let v5: {} = x; // Error let v6: {} | null | undefined = x; // Error // definimos el tipo let v10: number = x as number // Ok
2. No permite realizar operaciones con el valor hasta definir un tipo específico.
function sum(a:unknown, b: number) { // comprobando el tipo if(typeof a === "number"){ return a + b } throw new Error(`La variable '${a}' no es un número`); } sum(10,2) // 12 // Error sum("hola",2) // La variable 'hola' no es un número sum({a:5},2) // La variable [object Object] no es un número
Si recibimos objetos que no sabemos su tipo, lo definimos como unknown
para evitar que sea invocado directamente y haciendo uso de una interface
o type
podemos delimitar los atributos que queremos usar y si no está definido el atributo en nuestra interface
o type
TypeScript nos alertará.
// API y no conocemos su tipo const apiBook: unknown = { author: "author name", issn: "issn value" .... }; interface book { author: string issn: string } // definimos el tipo book const x = apiBook as book; console.log(x.author) // author name console.log(apiBook.author) // Error, Object is of type 'unknown'.
Cuidarnos de any
TypeScript nos provee dentro del archivo de configuración tsconfig.json una opción donde podemos definir la regla noImplicitAny
a true
para que TypeScript nos alerte cada vez que se usa un tipo any
.
{ "compilerOptions": { ... "noImplicitAny": true ... } }
O si quiere ir un paso más allá, (mi opción preferida y recomendada) es usar strict: true
{ "compilerOptions": { ... "strict": true ... } }
Esto habilitará las siguientes reglas:
noImplicitAny
noImplicitThis
strictNullChecks
alwaysStrict
Pero si hay una justificación válida para el uso de any
y deseamos usarlo sin desactivar nuestra regla podemos usar // @ts-ignore
, para ignorar todas las reglas.
// @ts-ignore const myApiVar:any = {} // no mostrará ninguna alerta
¿Cuales son los casos en que se puede usar any?
- Cuando hacemos migraciones de JavaScript a TypeScript, podemos marcar las variables como
any
para ir paso a paso y evitar de que se rompa todo. - Cuando estamos usando librerías de terceros y no tenemos un tipo disponible para ese dato, ejemplo la librería nos devuelve un tipo de dato
currency
y ese tipo no podemos importarlo a nuestro proyecto o no podemos reproducirlo.
¿Que otro caso consideras que se justifica usar any
?
Muchas gracias, me ha sido muy útil.
Me alegra mucho