Las intersecciones en TypeScript nos permiten combinar múltiples tipos en un solo tipo. Es decir, sirven para crear un tipo que suma las propiedades de dos tipos.
Sintaxis de intersecciones
Un tipo de intersección (Intersection Type
) se define utilizando el operador &
. El tipo resultante contiene todas las propiedades de los tipos combinados.
type TipoInterseccion = Tipo1 & Tipo2;
Donde Tipo1
y Tipo2
pueden ser cualquier tipo de objeto, interfaz, tipo primitivo, etc.
Vamos a verlo con un ejemplo,
type A = { a: number };
type B = { b: string };
type C = A & B;
// C es equivalente a { a: number; b: string }
En el ejemplo anterior,
- El tipo
C
es una intersección de los tiposA
yB
- Esto significa que
C
tendrá tanto la propiedada
del tipoA
como la propiedadb
del tipoB
.
Combinación de interfaces
Una de las formas más comunes de usar tipos de intersección es combinando interfaces. Esto es especialmente útil cuando queremos crear un objeto que tenga propiedades de varias interfaces:
interface Identificable {
id: number; // Propiedad id de tipo number
}
interface Nombrable {
nombre: string; // Propiedad nombre de tipo string
}
// Definimos un tipo Persona que es la intersección de Identificable y Nombrable
type Persona = Identificable & Nombrable;
const persona: Persona = {
id: 1,
nombre: "Luis"
};
console.log(persona.id); // Imprime: 1
console.log(persona.nombre); // Imprime: Luis
En este ejemplo,
Persona
es un tipo de intersección que combina las propiedades deIdentificable
yNombrable
- Por lo tanto,
persona
debe tener tanto unid
como unnombre
Extensión de tipos
Los tipos de intersección son útiles para extender tipos existentes (por ejemplo, si se quiere añadir propiedades adicionales a un tipo ya definido):
interface Base {
id: number;
}
type ConNombre = Base & { nombre: string };
const item: ConNombre = {
id: 1,
nombre: "Item 1"
};
En este ejemplo, ConNombre
extiende el tipo Base
añadiendo una propiedad nombre
.
Intersecciones con tipos genéricos
Las intersecciones pueden combinarse con tipos genéricos para crear tipos aún más flexibles y reutilizables.
function combinar<T, U>(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}
const objeto1 = { nombre: "Luis" };
const objeto2 = { edad: 30 };
const objetoCombinado = combinar(objeto1, objeto2);
console.log(objetoCombinado.nombre); // Luis
console.log(objetoCombinado.edad); // 30
En este ejemplo,
- La función
combinar
acepta dos objetos de tipos genéricosT
yU
- Retorna un objeto que es la intersección de ambos tipos.
Fijaros que es una forma elegante de destructurar dos objetos arbitrarios y combinarlos, manteniendo el tipado estático
Consideraciones y problemas
Intersecciones imposibles
Hay que tener cuidado al definir intersecciones de combinaciones de tipos primitivos, porque podemos dar lugar a tipos imposibles, que simplemente que no pueden ser satisfechos.
type Id = number;
type Nombre = string;
type Usuario = Id & Nombre;
const usuarioId: Usuario = 12345; // Error: no puede ser un número solo
const usuarioNombre: Usuario = "Luis"; // Error: no puede ser una cadena solo
En este ejemplo, el tipo Usuario
es imposible, porque una variable no puede ser a la vez number
y string
.
Intersección con Tipos any
Cuando se intersecta un tipo con any
, el resultado será any
. Por ejemplo:
type A = { a: number };
type B = any;
type C = A & B; // C es de tipo any