Tipos avanzados de TypeScript explicados con ejemplos
TypeScript ofrece varios tipos avanzados que van más allá de los tipos básicos, lo que permite sistemas de tipos más flexibles y potentes. Estos tipos avanzados ayudan a crear aplicaciones sólidas al proporcionar formas adicionales de definir y aplicar restricciones de tipos. Este artículo explora algunos de estos tipos avanzados con ejemplos.
Tipos de uniones
Los tipos de unión permiten que una variable sea de varios tipos. Esto puede resultar útil cuando un valor puede ser de varios tipos, pero debe manejarse de forma adecuada en función de su tipo real.
// Union type example
function formatValue(value: string | number): string {
if (typeof value === 'string') {
return `String: ${value}`;
} else {
return `Number: ${value.toFixed(2)}`;
}
}
console.log(formatValue("Hello"));
console.log(formatValue(123.456));
En este ejemplo, la función `formatValue` acepta una cadena o un número y formatea el valor en consecuencia.
Tipos de intersecciones
Los tipos de intersección combinan varios tipos en uno. Un objeto de un tipo de intersección tendrá todas las propiedades de los tipos combinados. Esto resulta útil para componer varios tipos juntos.
// Intersection type example
interface Person {
name: string;
age: number;
}
interface Contact {
email: string;
phone: string;
}
type Employee = Person & Contact;
const employee: Employee = {
name: "John Doe",
age: 30,
email: "john.doe@example.com",
phone: "123-456-7890"
};
console.log(employee);
Aquí, el tipo "Empleado" es una intersección de "Persona" y "Contacto", lo que significa que contiene propiedades de ambas interfaces.
Tipos literales
Los tipos literales especifican los valores exactos que puede contener una variable. Esto puede resultar especialmente útil para garantizar que solo se permitan determinados valores específicos.
// Literal type example
type Direction = "up" | "down" | "left" | "right";
function move(direction: Direction): void {
console.log(`Moving ${direction}`);
}
move("up"); // Valid
move("down"); // Valid
// move("side"); // Error: Argument of type '"side"' is not assignable to parameter of type 'Direction'.
El tipo `Dirección` aquí está restringido a cuatro valores de cadena específicos, lo que garantiza que solo estas direcciones se puedan usar en la función `mover`.
Tipos de tuplas
Los tipos de tuplas representan una matriz con una cantidad fija de elementos, donde cada elemento puede tener un tipo diferente. Las tuplas son útiles para representar colecciones de elementos heterogéneos de tamaño fijo.
// Tuple type example
let user: [string, number] = ["Alice", 30];
console.log(user[0]); // "Alice"
console.log(user[1]); // 30
// user = [30, "Alice"]; // Error: Type 'number' is not assignable to type 'string'.
La tupla `usuario` se define con una cadena seguida de un número, y esta estructura debe mantenerse.
Tipos condicionales
Los tipos condicionales permiten determinar los tipos en función de las condiciones. Proporcionan una forma de seleccionar un tipo u otro en función de una condición.
// Conditional type example
type IsString = T extends string ? "Yes" : "No";
type Test1 = IsString; // "Yes"
type Test2 = IsString; // "No"
En este ejemplo, el tipo `IsString` comprueba si un tipo `T` es una cadena. Devuelve `"Yes"` si lo es y `"No"` en caso contrario.
Tipos mapeados
Los tipos mapeados permiten crear nuevos tipos mediante la transformación de las propiedades de un tipo existente. Esto resulta útil para modificar o ampliar tipos existentes.
// Mapped type example
type ReadonlyPerson = {
readonly [K in keyof Person]: Person[K];
};
const readonlyPerson: ReadonlyPerson = {
name: "Alice",
age: 30
};
// readonlyPerson.age = 31; // Error: Cannot assign to 'age' because it is a read-only property.
El tipo `ReadonlyPerson` transforma el tipo `Person` haciendo que todas sus propiedades sean de solo lectura.
Conclusión
Los tipos avanzados de TypeScript proporcionan herramientas potentes para definir y gestionar requisitos de tipos complejos. Al utilizar tipos de unión, intersección, literales, tuplas, condicionales y mapeados, los desarrolladores pueden crear aplicaciones más sólidas y fáciles de mantener. Comprender y aplicar estos tipos de manera eficaz puede mejorar significativamente la seguridad de tipos y la flexibilidad del código TypeScript.