En TypeScript, las guardias de tipo (type guards) son una técnica que permite a los desarrolladores verificar el tipo de una variable en tiempo de ejecución. Esto es especialmente útil cuando se trabaja con tipos de unión, ya que permite a TypeScript inferir el tipo específico de una variable dentro de un bloque de código.
Conceptos Clave
- Guardias de Tipo con
typeof
: Utilizado para verificar tipos primitivos comostring
,number
,boolean
, etc. - Guardias de Tipo con
instanceof
: Utilizado para verificar si un objeto es una instancia de una clase específica. - Guardias de Tipo Personalizadas: Funciones que devuelven un predicado de tipo, permitiendo verificaciones más complejas.
Guardias de Tipo con typeof
El operador typeof
se utiliza para verificar el tipo de una variable en tiempo de ejecución. Es útil para tipos primitivos.
function padLeft(value: string, padding: string | number) { if (typeof padding === "number") { return Array(padding + 1).join(" ") + value; } if (typeof padding === "string") { return padding + value; } throw new Error(`Expected string or number, got '${typeof padding}'.`); } // Ejemplo de uso console.log(padLeft("Hello", 4)); // " Hello" console.log(padLeft("Hello", ">>")); // ">>Hello"
En este ejemplo, typeof padding
se utiliza para determinar si padding
es un number
o un string
, y se maneja cada caso en consecuencia.
Guardias de Tipo con instanceof
El operador instanceof
se utiliza para verificar si un objeto es una instancia de una clase específica.
class Bird { fly() { console.log("Flying"); } } class Fish { swim() { console.log("Swimming"); } } type Pet = Bird | Fish; function move(pet: Pet) { if (pet instanceof Bird) { pet.fly(); } else if (pet instanceof Fish) { pet.swim(); } } // Ejemplo de uso const myBird = new Bird(); const myFish = new Fish(); move(myBird); // "Flying" move(myFish); // "Swimming"
En este ejemplo, instanceof
se utiliza para verificar si pet
es una instancia de Bird
o Fish
, y se llama al método correspondiente.
Guardias de Tipo Personalizadas
Las guardias de tipo personalizadas son funciones que devuelven un predicado de tipo. Estas funciones permiten verificaciones más complejas y específicas.
interface Cat { meow(): void; } interface Dog { bark(): void; } function isCat(pet: Cat | Dog): pet is Cat { return (pet as Cat).meow !== undefined; } function makeSound(pet: Cat | Dog) { if (isCat(pet)) { pet.meow(); } else { pet.bark(); } } // Ejemplo de uso const myCat: Cat = { meow: () => console.log("Meow") }; const myDog: Dog = { bark: () => console.log("Bark") }; makeSound(myCat); // "Meow" makeSound(myDog); // "Bark"
En este ejemplo, isCat
es una guardia de tipo personalizada que verifica si pet
es un Cat
. La función makeSound
utiliza esta guardia para determinar el tipo de pet
y llamar al método correspondiente.
Ejercicio Práctico
Ejercicio
Crea una función getArea
que acepte un parámetro de tipo Shape
, que puede ser un Circle
o un Rectangle
. La función debe devolver el área de la forma. Utiliza guardias de tipo para determinar el tipo de la forma y calcular el área correctamente.
interface Circle { kind: "circle"; radius: number; } interface Rectangle { kind: "rectangle"; width: number; height: number; } type Shape = Circle | Rectangle; function getArea(shape: Shape): number { // Implementa la función aquí } // Ejemplo de uso const myCircle: Circle = { kind: "circle", radius: 10 }; const myRectangle: Rectangle = { kind: "rectangle", width: 5, height: 10 }; console.log(getArea(myCircle)); // 314.159... console.log(getArea(myRectangle)); // 50
Solución
function getArea(shape: Shape): number { if (shape.kind === "circle") { return Math.PI * shape.radius * shape.radius; } else if (shape.kind === "rectangle") { return shape.width * shape.height; } throw new Error("Unknown shape"); } // Ejemplo de uso const myCircle: Circle = { kind: "circle", radius: 10 }; const myRectangle: Rectangle = { kind: "rectangle", width: 5, height: 10 }; console.log(getArea(myCircle)); // 314.159... console.log(getArea(myRectangle)); // 50
Conclusión
Las guardias de tipo son una herramienta poderosa en TypeScript que permite a los desarrolladores manejar tipos de manera segura y eficiente en tiempo de ejecución. Al utilizar typeof
, instanceof
y guardias de tipo personalizadas, puedes escribir código más robusto y menos propenso a errores. En el siguiente módulo, exploraremos los tipos mapeados, que te permitirán transformar tipos de manera más avanzada y flexible.
Curso de TypeScript
Módulo 1: Introducción a TypeScript
- ¿Qué es TypeScript?
- Configuración del Entorno de TypeScript
- Tipos Básicos
- Anotaciones de Tipo
- Compilando TypeScript
Módulo 2: Trabajando con Tipos
Módulo 3: Tipos Avanzados
Módulo 4: Funciones y Módulos
- Tipos de Función
- Parámetros Opcionales y Predeterminados
- Parámetros Rest
- Módulos y Espacios de Nombres
- Decoradores
Módulo 5: Programación Asíncrona
Módulo 6: Herramientas y Mejores Prácticas
- Linting y Formateo
- Pruebas de Código TypeScript
- TypeScript con Webpack
- TypeScript con React
- Mejores Prácticas