← TypeScript EspañolChapter 08 of 12

Tipos Union y Guardas de Tipo

## Objetivos de Aprendizaje - Crear y usar tipos union - Trabajar con uniones discriminadas - Dominar guardas de tipo - Reducir tipos efectivamente - Manejar null y undefined ## Tipos Union ### Sintaxis Basica ```typescript let id: string | number; id = "ABC123"; // OK id = 456; // OK // id = true; // Error ``` ### En Funciones ```typescript function printId(id: string | number): void { console.log(`ID: ${id}`); } printId("ABC123"); // OK printId(456); // OK ``` ## Operaciones de Tipo Union ### Operaciones Limitadas ```typescript function printId(id: string | number): void { // id.toUpperCase(); // Error: number no tiene toUpperCase if (typeof id === "string") { console.log(id.toUpperCase()); // OK dentro del bloque } else { console.log(id.toFixed(2)); // OK dentro del bloque } } ``` ## Uniones Discriminadas ### Propiedad Comun ```typescript interface Circle { kind: "circle"; radius: number; } interface Square { kind: "square"; side: number; } type Shape = Circle | Square; function area(shape: Shape): number { if (shape.kind === "circle") { return Math.PI * shape.radius ** 2; } else { return shape.side ** 2; } } ``` ### Ejemplo: Respuestas de API ```typescript interface SuccessResponse { status: "success"; data: User[]; } interface ErrorResponse { status: "error"; message: string; } type ApiResponse = SuccessResponse | ErrorResponse; function handleResponse(response: ApiResponse): void { if (response.status === "success") { console.log(response.data); } else { console.error(response.message); } } ``` ## Guardas de Tipo ### typeof ```typescript function print(value: string | number): void { if (typeof value === "string") { console.log(value.toUpperCase()); } else { console.log(value.toFixed(2)); } } ``` ### instanceof ```typescript class Dog { bark(): void { console.log("Guau!"); } } class Cat { meow(): void { console.log("Miau!"); } } function speak(animal: Dog | Cat): void { if (animal instanceof Dog) { animal.bark(); } else { animal.meow(); } } ``` ### Verificacion de Propiedad ```typescript interface Book { title: string; author: string; } interface Magazine { name: string; issue: number; } function print(item: Book | Magazine): void { if ("title" in item) { console.log(item.title, item.author); } else { console.log(item.name, item.issue); } } ``` ## Guardas de Tipo Personalizadas ### Funcion Retorna boolean ```typescript interface Person { name: string; age: number; } interface Animal { name: string; species: string; } function isPerson(obj: any): obj is Person { return "age" in obj && typeof obj.age === "number"; } function check(obj: Person | Animal): void { if (isPerson(obj)) { console.log(obj.age); } else { console.log(obj.species); } } ``` ### Predicado de Tipo ```typescript function isString(value: unknown): value is string { return typeof value === "string"; } function process(value: unknown): void { if (isString(value)) { console.log(value.toUpperCase()); // TypeScript sabe que es string } } ``` ## Null y Undefined ### Tipos Anulables ```typescript let name: string | null = null; name = "Alice"; // name = undefined; // Error si no esta en el tipo ``` ### Encadenamiento Opcional ```typescript interface User { address?: { city: string; }; } let user: User = {}; // Forma antigua let city = user && user.address && user.address.city; // Encadenamiento opcional let city2 = user?.address?.city; // undefined si falta ``` ### Fusion Nula ```typescript let name: string | null = null; // Valor por defecto cuando null/undefined let displayName = name ?? "Anonimo"; // vs || (tambien captura cadena vacia) let empty = ""; let result = empty ?? "por defecto"; // "" let result2 = empty || "por defecto"; // "por defecto" ``` ## Reduccion de Tipos ### En Bloque else ```typescript function process(value: string | number | null): void { if (value === null) { console.log("valor null"); } else { // TypeScript sabe: string | number console.log(value); } } ``` ### Despues de throw ```typescript function process(value: string | null): void { if (value === null) { throw new Error("El valor es null"); } // value es string aqui console.log(value.toUpperCase()); } ``` ### Tipo Never Despues de Agotamiento ```typescript function process(value: string | number): string { if (typeof value === "string") { return value.toUpperCase(); } // value es number aqui return value.toFixed(2); } ``` ## Tipos Interseccion ### Sintaxis de Tipos Interseccion ```typescript interface A { a: string; } interface B { b: number; } type AB = A & B; let obj: AB = { a: "hola", b: 42 }; ``` ### Combinar Uniones ```typescript type UnionA = "a" | "b"; type UnionB = 1 | 2; type Combined = UnionA & UnionB; // Combined = "a" & 1 | "a" & 2 | "b" & 1 | "b" & 2 // = never (en la mayoria de casos) ``` ## typeof para Variables ```typescript const config = { host: "localhost", port: 8080, debug: true }; type Config = typeof config; // { // host: string; // port: number; // debug: boolean; // } ``` ## Keyof Obtener claves como tipo union: ```typescript interface User { id: number; name: string; email: string; } type UserKeys = keyof User; // "id" | "name" | "email" function getProperty(obj: T, key: K): T[K] { return obj[key]; } let user: User = { id: 1, name: "Alice", email: "alice@example.com" }; getProperty(user, "name"); // string ``` ## Uniones Exhausivas ### Never en Default ```typescript type Shape = Circle | Square | Triangle; function area(shape: Shape): number { switch (shape.kind) { case "circle": return Math.PI * shape.radius ** 2; case "square": return shape.side ** 2; case "triangle": return 0.5 * shape.base * shape.height; default: { // Si anadimos una nueva forma, esto lo captura const _exhaustive: never = shape; return _exhaustive; } } } ``` ## Resumen - Tipos union: `string | number` permite cualquiera - Las uniones discriminadas usan una propiedad `kind` comun - Las guardas de tipo reducen tipos: `typeof`, `instanceof`, verificaciones de propiedad - Guardas personalizadas: retorno `obj is Type` - Encadenamiento opcional: `obj?.prop?.nested` - Fusion nula: `value ?? valorPorDefecto` - Tipos interseccion: `A & B` - Keyof obtiene union de claves de objeto - Usar `never` para verificacion exhaustiva

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →