ProgramaciónDesarrollador Fullstack

Describe el mecanismo de tipos de intersección (Intersection Types) en TypeScript. ¿Cómo se pueden implementar tipos combinados con ellos, cuál es la diferencia con los tipos de unión y cuáles son las principales sutilezas al heredar y la compatibilidad de propiedades?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

Los tipos de intersección (Intersection Types) en TypeScript permiten crear tipos compuestos que combinan propiedades y métodos de todos los tipos originales. Esta es una herramienta poderosa para construir estructuras de datos flexibles y extensibles sin la necesidad de una herencia excesiva de clases. La construcción se realiza mediante el operador & entre tipos.

Historia de la cuestión

TypeScript ha soportado tipos de unión (|) desde las primeras versiones para expresar “o”, pero a menudo surge la necesidad de describir un objeto con múltiples propiedades de diferentes interfaces o tipos independientes. En este caso, se utiliza la intersección (&) — el objeto debe cumplir con todos los interfaces en todas las propiedades.

Problema

Una de las principales dificultades es el conflicto de nombres idénticos de propiedades en tipos intersectados, las diferencias en su tipificación, así como la corrección del tipo combinado resultante, si se combinan clases con campos privados o protegidos. También se confunden a menudo los tipos de intersección con los tipos de unión (union types), lo que lleva a errores de compilación o a un comportamiento inesperado con el objeto.

Solución

La intersección de tipos agrega todas las propiedades de los tipos que se unen, y para cada propiedad se requiere que sea compatible con ambos tipos si los nombres coinciden. Se utiliza tanto para interfaces como para alias de tipo.

interface A { foo: string; } interface B { bar: number; } type AB = A & B; const item: AB = { foo: "hello", bar: 123 }; // Correcto

Si se intersectan propiedades con el mismo nombre, el tipo debe coincidir, de lo contrario, se produce un error:

interface X { val: string; } interface Y { val: number; } // type Z = X & Y; // Error: incompatibilidad val

Características clave:

  • El operador & combina todas las propiedades de ambos tipos (interfaces y alias de tipo).
  • Si una propiedad está presente en ambos tipos, el tipo resultante es su intersección (debe cumplir simultáneamente con ambos).
  • Se utiliza para combinar funcionalidades de manera flexible sin necesidad de crear nuevas clases o jerarquías.

Preguntas con trampa.

¿Qué sucede si los tipos se intersectan y algunas propiedades tienen tipos incompatibles? (Por ejemplo, una propiedad es string, otra number)

Habrá un error de compilación, ya que la propiedad no puede ser tanto string como number al mismo tiempo.

¿Se pueden intersectar clases con propiedades privadas o protegidas?

Se puede, pero si existen dichos campos con nombres idénticos y diferentes tipos de acceso, el resultado será inválido y TypeScript generará un error.

¿En qué se diferencia el tipo de intersección del tipo de unión (|)?

La intersección (A & B) requiere que el objeto sea de ambos tipos simultáneamente, mientras que la unión (A | B) requiere que sea al menos uno de ellos. Por ejemplo:

type U = A | B; // Puede ser foo o bar o ambos type I = A & B; // Debe tener ambas propiedades

Errores típicos y anti-patrones

  • Intersección de tipos incompatibles o conflictos de propiedades con diferentes tipos — llevarán a errores.
  • Abusar de la intersección para evitar la tipificación estricta hace que el código sea confuso.

Ejemplo de la vida real

Caso negativo

Un desarrollador crea un tipo a través de la intersección de varias interfaces no concordadas; las propiedades entran en conflicto y surgen errores de tipificación difíciles de depurar.

Ventajas: Capacidad de combinar rápidamente las capacidades de varios tipos

Desventajas: El código no compila o contiene errores implícitos, la depuración es difícil

Caso positivo

Separar funciones en interfaces independientes y combinar cuidadosamente a través de tipo de intersección para formar objetos compuestos finales.

Ventajas: Escalabilidad, facilidad de prueba y expansión, contrato estricto

Desventajas: Trabajo adicional en el diseño de interfaces y su concordancia