Intersection Types en TypeScript
En la clase anterior vimos los literal types y ahora toca uno de esos conceptos que, cuando te hace click, empiezas a modelar datos como un profesional: los intersection types.
Un intersection type es la forma de decirle a TypeScript:
“Este tipo tiene que cumplir más de uno a la vez.”
¿Qué es un Intersection Type?
Si con un union type (A | B) el valor puede ser uno u otro, con un intersection type (A & B) el valor debe ser ambos.
Piensa en ello como combinar contratos.
Ejemplo: construir una entidad combinando tipos
Imaginemos estos tipos:
type User = {
age: number
email: string
company: string
}
type UserId = {
id: string | number
}
Ahora podemos combinarlos con &:
type UserWithId = User & UserId
El resultado es un tipo que exige todas las propiedades de ambos:
const user: UserWithId = {
id: 1,
age: 30,
email: 'midu@dev.com',
company: 'midudev',
}
Si te falta alguna propiedad, TypeScript te grita. Y si sobra alguna que no está en ninguno de los dos tipos, también.
¿Por qué no meter todo en un solo tipo?
Podrías hacer un único tipo con todas las propiedades, sí. Pero la gracia de las intersecciones es la composición:
Userpuede usarse en sitios donde no necesitas elid.UserIdpuede reutilizarse con otras entidades (productos, comentarios, etc.).UserWithIdcombina ambos solo donde haga falta.
Es el mismo principio de no repetirte que aplicamos en código normal.
Intersection vs Union: la diferencia clave
// Union: puede ser uno u otro
type StringOrNumber = string | number
// Intersection: debe cumplir ambos
type UserWithId = User & UserId
- Union (
|): el valor cumple al menos uno de los tipos. - Intersection (
&): el valor cumple todos los tipos a la vez.
Caso práctico: extensión de entidades
Imagina que tienes una base común y quieres extenderla:
type BaseEntity = {
id: string
createdAt: Date
updatedAt: Date
}
type Product = {
name: string
price: number
}
type ProductWithMeta = Product & BaseEntity
Ahora ProductWithMeta tiene name, price, id, createdAt y updatedAt. Todo validado, todo con autocompletado.
¿Qué pasa si los tipos tienen propiedades en conflicto?
Si combinas tipos que tienen la misma propiedad con tipos distintos, TypeScript resuelve la intersección de esos tipos:
type A = { value: string }
type B = { value: number }
type C = A & B
// value sería string & number → never (imposible de satisfacer)
Esto es algo a tener en cuenta: si dos tipos son incompatibles en una propiedad, el resultado será never y no podrás crear un valor válido.
Buenas prácticas
- Usa intersecciones para componer tipos pequeños en lugar de crear tipos gigantes.
- Nombra los tipos intermedios de forma semántica:
UserWithId,ProductWithMeta, etc. - Si ves que un tipo crece demasiado, pregúntate si puedes descomponerlo con
&.
Resumen
- Los intersection types combinan varios tipos con
&. - El valor resultante debe cumplir todos los tipos a la vez.
- Son ideales para componer entidades sin repetir propiedades.
- Si hay propiedades en conflicto, el resultado es
never. - La diferencia con union (
|): union es “uno u otro”, intersection es “todos a la vez”.