TypeScript para devs junior: lo que nadie te explica del `any`
Por Equipo Hexadevs · 5 jul 2026 · 3 min de lectura
TypeScript no es JavaScript con tipos por encima: es un lenguaje distinto que te avisa en tiempo de desarrollo qué partes de tu código van a romperse en producción. La diferencia entre usarlo bien y usarlo mal está en tres decisiones que tomás en las primeras dos semanas.
El error de origen: usar any para callar al compilador
function procesar(data: any) {
return data.nombre.toUpperCase() // sin error, hasta que data sea undefined
}
any desactiva TypeScript en ese punto. Es como no tenerlo. Y es contagioso: si una función devuelve any, todo lo que la usa se vuelve any.
La alternativa segura para esos casos no es un cast: es unknown.
function procesar(data: unknown) {
// unknown obliga a chequear antes de usar
if (typeof data === "object" && data !== null && "nombre" in data) {
return String(data.nombre).toUpperCase()
}
return null
}
unknown es el tipo seguro por defecto cuando no sabés qué llega. Te obliga a validar.
Tipos primitivos y unions: el 90% de lo que vas a escribir
let nombre: string = "Hexadevs"
let edad: number = 5
let activo: boolean = true
let ids: number[] = [1, 2, 3]
let tupla: [string, number] = ["hola", 1]
// Unions: el tipo es A o B
type Estado = "activo" | "inactivo" | "pendiente"
type ID = string | number
function setEstado(e: Estado) { /* ... */ }
Las unions de literales ("activo" | "inactivo") son el patrón más potente de TS: el compilador te avisa si pasás un string que no estaba en la lista.
Narrowing: dejar que TS te ayude de verdad
function imprimir(valor: string | number | null) {
if (valor === null) {
return "vacío"
}
if (typeof valor === "string") {
return valor.toUpperCase() // TS sabe que es string acá
}
return valor.toFixed(2) // TS sabe que es number acá
}
Cada if con typeof, instanceof o un discriminante reduce el universo de tipos posibles. TS rastrea eso y ajusta el autocomplete, las propiedades disponibles y los errores. Acompañá el flujo con type guards en vez de castear.
Interfaces vs types: no es la discusión que importa
interface Usuario {
nombre: string
email: string
}
type UsuarioConRol = Usuario & { rol: "admin" | "editor" }
Regla que usamos: interface para objetos que se pueden extender, type para unions, intersections y primitivos compuestos. La diferencia práctica es mínima en la mayoría de los proyectos.
Los as y ! son deuda técnica, no soluciones
const usuario = data as Usuario // le decís "confía en mí"
const nombre = (data as any).nombre! // doble negligencia
Cada as en tu código es un lugar donde TypeScript deja de cuidarte. Antes de castear, preguntate si lo correcto es mejorar el tipo, no silenciar el error.
Lo que TypeScript NO te resuelve
- Lógica incorrecta. Que compile no significa que funcione.
- Tipos de librerías mal definidas. Si una dependencia no tiene tipos, es una bandera roja seria.
- Runtime: los tipos desaparecen en producción. Validá en los bordes con Zod u otra herramienta.
Una regla que repetimos en code review: si necesitás
anyo un cast, escribí un comentario explicando por qué. Si no podés explicar el cast en una línea, es un problema de tipos, no del compilador.
TypeScript bien usado te hace más rápido: el editor autocompleta correctamente, los errores aparecen donde los cometés y los refactors masivos se hacen con un click. La promesa se cumple solo si lo dejás trabajar.