Lecciones del módulo (1/2)
Guardias de Tipo
El estrechamiento de tipos (Type Narrowing) es uno de los conceptos más importantes en TypeScript. A menudo, sin embargo, las guardas de tipo estándar como typeof o instanceof no son suficientes para objetos personalizados complejos. Aquí es donde entran en juego las Guardas de Tipo Personalizadas (Custom Type Guards).
Guardas de Tipo Estándar
Comencemos resumiendo cómo TypeScript restringe los tipos usando los operadores estándar de JavaScript:
function processInput(val: string | number) {
if (typeof val === 'string') {
// Qui 'val' è di tipo string
console.log(val.toUpperCase());
} else {
// Qui 'val' è di tipo number
console.log(val.toFixed(2));
}
}Guardas de Tipo Personalizadas (operador is)
Para definir una guarda de tipo personalizada, creamos una función que devuelve un predicado de tipo en el formato parameterName is Type en lugar del tipo de retorno booleano estándar.
La función debe devolver un booleano (true o false). Si devuelve true, TypeScript sabrá que el parámetro pasado es del tipo especificado.
interface Cat {
name: string;
meow(): void;
}
interface Dog {
name: string;
bark(): void;
}
// Questa è una guardia di tipo personalizzata
function isCat(animal: Cat | Dog): animal is Cat {
return (animal as Cat).meow !== undefined;
}
function makeNoise(pet: Cat | Dog) {
if (isCat(pet)) {
// Qui TypeScript sa che 'pet' è un Cat
pet.meow();
} else {
// Qui TypeScript sa che 'pet' è un Dog
pet.bark();
}
}Seguridad y Conversión (as vs Type Guards)
El type casting (ej. val as Cat) obliga al compilador a confiar en el desarrollador, sin ninguna verificación real en tiempo de ejecución. Si el objeto en tiempo de ejecución no cumple con las expectativas, el código fallará silenciosamente o lanzará excepciones.
Las guardas de tipo personalizadas permiten, en cambio, realizar una verificación robusta y dinámica en tiempo de ejecución, informando de forma segura y precisa al compilador de TypeScript sobre el tipo real de la variable:
function processInput(input: unknown) {
// casting insicuro: potrebbe rompersi se input non ha il metodo split
// const str = input as string;
// console.log(str.split(' '));
// guardia sicura
if (isString(input)) {
console.log(input.split(' ')); // Sicuro al 100%!
}
}Pruébalo tú
Ejercicio 1: Guarda de Tipo para Cadenas
Crea una función simple llamada isString que funcione como guarda de tipo personalizada para verificar si un valor unknown es una cadena.
Mostrar pista
El tipo de retorno de la función debe ser val is string, y debes usar typeof para verificar si es igual a 'string'.
Solución disponible después de 3 intentos
Ejercicio 2: Guarda de Tipo para Usuario Premium
Dados los tipos User y PremiumUser, escribe una función de guarda de tipo isPremiumUser(user: User): user is PremiumUser que verifique si el usuario tiene el rol 'premium'.
Mostrar pista
Define la firma como function isPremiumUser(user: User): user is PremiumUser y compara user.role con 'premium'.
Solución disponible después de 3 intentos
Ejercicio 3: Verificación de Objeto de Error Personalizado
Implementa la función isCustomError(err: unknown): err is CustomError que verifique si un valor desconocido es un objeto CustomError no nulo que posee la clave 'code'.
Mostrar pista
Verifica primero que typeof err sea 'object' y no sea null, luego usa el operador 'in' para verificar la presencia de la propiedad 'code'.
Solución disponible después de 3 intentos
Ejercicio 4: Guarda de Tipo Admin
Dadas dos interfaces User (con propiedad role: string) y Admin (que extiende User y tiene una propiedad adminToken: string), escribe una función type guard llamada isAdmin que acepte un objeto user de tipo User y devuelva un predicado de tipo user is Admin. La guarda debe verificar que el role del usuario sea igual a 'admin'.
Mostrar pista
Define la firma como function isAdmin(user: User): user is Admin y controla que user.role === 'admin'.
Solución disponible después de 3 intentos