Combina lo Incombinable: Un Vistazo Profundo a los Tipos Combinados en TypeScript

Pablo Contreras
4 min readJun 3, 2023

--

¡Hola TypeScripters! Aquí estamos nuevamente, listos para desentrañar más secretos de nuestro querido TypeScript. Si pensabas que ya habías visto todo lo que TypeScript tiene para ofrecer, déjame decirte algo: ¡Estás a punto de entrar en la zona del “Twilight TypeScript”! 😄

En nuestras entregas anteriores, hemos aprendido y jugado con las sutilezas de TypeScript, dominando los conceptos básicos y construyendo una sólida base sobre la que vamos a erigir algo grandioso hoy. Sí, queridos lectores, hoy hablaremos de “Combining Types”. Si estás pensando “¿Cómo? ¿No es eso como intentar mezclar agua y aceite?”, bueno… ¡prepárate para sorprenderte! Porque en el mundo de TypeScript, la magia sucede y el agua y el aceite pueden, de hecho, mezclarse. Así que sin más preámbulos, ¡sumérgete conmigo en el fascinante mundo de los “Combining Types”!

En TypeScript, puedes combinar tipos usando uniones de tipos (Type Union) e intersecciones de tipos (Type Intersection). ¿Suena como un cruce de carreteras en el mundo de la codificación, verdad? Bueno, no estás lejos de la realidad. Pero no te preocupes, no necesitas ser un controlador de tráfico para manejarlo. 😄

Type Union

El operador de unión | se utiliza para combinar dos o más tipos en un solo tipo que representa todos los posibles tipos. Imagínalo como un superhéroe que puede tener los poderes de Superman y Flash al mismo tiempo. Y sí, es tan genial como suena.

Ejemplos y Casos de Éxito/Error

Ejemplo 1

type FavoriteFood = "pizza" | "hamburguesa" | "ensalada";

let myFood: FavoriteFood = "pizza";

Aquí, myFood puede ser "pizza", "hamburguesa" o "ensalada". Nada más.

Caso de éxito: Asignar “hamburguesa” a myFood.

myFood = "hamburguesa"; // Esto es correcto

Caso de error: Intentar asignar “sushi” a myFood.

myFood = "sushi"; // Error: Type '"sushi"' is not assignable to type 'FavoriteFood'.

Ejemplo 2

type ErrorCode = 404 | 500 | 502;

let myErrorCode: ErrorCode = 404;

Caso de éxito: Asignar 500 a myErrorCode.

myErrorCode = 500; // Esto es correcto

Caso de error: Intentar asignar 200 a myErrorCode.

myErrorCode = 200; // Error: Type '200' is not assignable to type 'ErrorCode'.

Ejemplo 3

type Point = [number, number] | [number, number, number];

let myPoint: Point = [1, 2];

Caso de éxito: Asignar [3, 4, 5] a myPoint.

myPoint = [3, 4, 5]; // Esto es correcto

Caso de error: Intentar asignar [6, 7, 8, 9] a myPoint.

myPoint = [6, 7, 8, 9]; // Error: Type '[number, number, number, number]' is not assignable to type 'Point'.

Como puedes ver, los Type Unions son como el portero de un club exclusivo. Solo dejan entrar a los que están en la lista.😎

Type Intersection

Pasando al otro lado de la carretera, encontramos al operador de intersección &. Se utiliza para intersectar dos o más tipos en un solo tipo que representa las propiedades de todos los tipos. Puedes pensar en él como un súper robot formado por la combinación de varios robots más pequeños, cada uno con sus propias habilidades únicas. ¡Es hora de formar Voltron!

Ejemplos y Casos de Éxito/Error

Ejemplo 1

interface CanWalk {
walk: () => void;
}

interface CanSwim {
swim: () => void;
}

type Amphibian = CanWalk & CanSwim;

let frog: Amphibian = {
walk: () => console.log("Walking..."),
swim: () => console.log("Swimming...")
};

En este caso, frog es un anfibio, por lo que debe poder caminar y nadar.

Caso de éxito: Asignar una función de vuelo a frog.

frog = {
walk: () => console.log("Walking..."),
swim: () => console.log("Swimming..."),
fly: () => console.log("Flying...") // Esto es correcto
};

Caso de error: Intentar asignar un objeto que solo puede caminar a frog.

frog = {
walk: () => console.log("Walking...")
}; // Error: Type '{ walk: () => void; }' is not assignable to type 'Amphibian'.

Ejemplo 2

interface HasName {
name: string;
}

interface CanBark {
bark: () => void;
}

type Dog = HasName & CanBark;

let myDog: Dog = {
name: "Fido",
bark: () => console.log("Woof!")
};

Aquí, myDog debe tener un nombre y poder ladrar.

Caso de éxito: Asignar un nuevo objeto a myDog que pueda ladrar y maullar.

myDog = {
name: "Rex",
bark: () => console.log("Woof!"),
meow: () => console.log("Meow!") // Esto es correcto
};

Caso de error: Intentar asignar un objeto que solo tiene nombre a myDog.

myDog = {
name: "Max"
}; // Error: Type '{ name: string; }' is not assignable to type 'Dog'.

Ejemplo 3

interface IsSolid {
density: number;
}

interface CanFloat {
buoyancy: number;
}

type FloatingSolid = IsSolid & CanFloat;

let iceberg: FloatingSolid = {
density: 920, // kg/m^3
buoyancy: 1.1 // relative to water
};

Aquí, iceberg debe tener una densidad y una flotabilidad.

Caso de éxito: Asignar un nuevo objeto a iceberg con densidad, flotabilidad y temperatura.

iceberg = {
density: 930,
buoyancy: 1.0,
temperature: -10 // Esto es correcto
};

Caso de error: Intentar asignar un objeto que solo tiene densidad a iceberg.

iceberg = {
density: 940
}; // Error: Type '{ density: number; }' is not assignable to type 'FloatingSolid'.

Como puedes ver, las intersecciones de tipos son como un potluck de programación: todo el mundo tiene que traer algo a la mesa. 😄

¡Y eso es todo para hoy, TypeScripters! Espero que hayas disfrutado de este viaje a través de los ‘Combining Types’. Antes de despedirnos, aquí tienes un poco de humor para alegrar tu día:

“Toc, toc.”

“¿Quién es?”

(larga pausa…)

“Java.”

Si te ha gustado este boletín, ¡no olvides suscribirte para recibir más contenido como este! Y si te has reído con las bromas, ¡comparte este post con tus amigos! Así me ayudas a crecer y a llevar el humor y el aprendizaje de TypeScript a más personas.

¡Hasta la próxima edición de nuestra newsletter! Manténganse codificando y riendo, amigos. 🚀😄

--

--

Pablo Contreras

Desarrollador con conocimientos en JS, TS y Python. Construí soluciones para restaurantes y fintech. Aprendiendo y compartiendo en mi newsletter.