Type Narrowing en TypeScript
En esta clase nos metemos con una técnica clave para escribir TypeScript sin pelearte con el compilador: el type narrowing (estrechamiento de tipos). La idea es simple: partir de un tipo amplio (por ejemplo, una unión) y reducirlo a uno más específico usando comprobaciones.
Qué es el type narrowing
Type narrowing es la técnica de reducir un tipo más amplio a uno más concreto mediante comprobaciones en tiempo de ejecución que TypeScript sabe interpretar.
Ejemplo típico: un valor que puede ser number | string.
function procesar(valor: number | string) {
// aquí: valor es number | string
}
Narrowing con typeof
Cuando trabajas con primitivas, typeof es el clásico.
function procesar(valor: number | string) {
if (typeof valor === 'number') {
// aquí: valor es number
return valor.toFixed(2)
}
// aquí: valor es string
return valor.toUpperCase()
}
Esto funciona porque al comprobar typeof, TypeScript descarta tipos automáticamente y te deja el correcto dentro de cada rama.
Narrowing con truthy/falsy
No todo narrowing es typeof. Cuando un valor puede ser string | null | undefined, un simple if (valor) ya descarta null y undefined (porque son falsy).
function imprimirMensaje(mensaje: string | null | undefined) {
if (mensaje) {
// aquí: mensaje es string
console.log(mensaje.trim())
return
}
// aquí: mensaje es null | undefined
console.log('No hay mensaje')
}
Esto te ahorra dos comprobaciones de golpe.
Operator narrowing con in
Para objetos, puedes estrechar mirando si existe una propiedad o método usando in.
type Pez = { nombre: string; nadar: () => void }
type Pajaro = { nombre: string; volar: () => void }
type Perro = { nombre: string; ladrar: () => void }
type Animal = Pez | Pajaro | Perro
function mover(animal: Animal) {
if ('nadar' in animal) {
// animal es Pez
animal.nadar()
return
}
if ('volar' in animal) {
// animal es Pajaro
animal.volar()
return
}
// animal es Perro
animal.ladrar()
}
Solo por comprobar “si tiene nadar”, TypeScript sabe que estás ante un Pez.
Narrowing con instanceof
Cuando una variable puede venir como Date | string, instanceof es el recurso típico para fechas (y para errores, clases, etc.).
function formatDate(value: Date | string) {
if (value instanceof Date) {
// value es Date
return value.toISOString()
}
// value es string
return new Date(value).toISOString()
}
De nuevo: comprobación sencilla, tipo estrechado, y código más seguro.
Idea clave para quedarte
El type narrowing no es “aprenderte typeof”. Es entender que TypeScript te acompaña cuando descartas posibilidades: por tipo, por truthiness, por propiedades, por instancias, etc. Tú vas cerrando puertas y el compilador hace el resto.
Resumen
- Type narrowing es reducir un tipo amplio a uno concreto con comprobaciones.
typeoffunciona para primitivas:string,number,boolean, etc.- Truthy/falsy descarta
nullyundefinedde un plumazo. incomprueba si un objeto tiene una propiedad y estrecha entre tipos de unión.instanceoffunciona con clases y constructores comoDate,Error, etc.- TypeScript te acompaña: tú descartas opciones y él infiere el tipo correcto.