← TypeScript EspañolChapter 06 of 12

Genericos

## Objetivos de Aprendizaje - Crear funciones genericas - Definir clases genericas - Usar interfaces genericas - Aplicar restricciones de tipo - Dominar tipos de utilidad ## Por que Genericos? ### Sin Genericos ```typescript function identity(arg: any): any { return arg; } let num = identity(42); // tipo: any let str = identity("hola"); // tipo: any // Informacion de tipo perdida ``` ### Con Genericos ```typescript function identity(arg: T): T { return arg; } let num = identity(42); // tipo: number let str = identity("hola"); // tipo: string // Informacion de tipo preservada ``` ## Funciones Genericas ### Sintaxis ```typescript function firstElement(arr: T[]): T | undefined { return arr[0]; } let num = firstElement([1, 2, 3]); // number | undefined let str = firstElement(["a", "b", "c"]); // string | undefined ``` ### Multiples Parametros de Tipo ```typescript function pair(first: T, second: U): [T, U] { return [first, second]; } let p = pair("hola", 42); // [string, number] ``` ## Interfaces Genericas ### Declaracion ```typescript interface Container { value: T; getValue(): T; } class Box implements Container { constructor(public value: T) {} getValue(): T { return this.value; } } let stringBox = new Box("hola"); let numBox = new Box(42); ``` ### Interface Generica con Multiples Parametros de Tipo ```typescript interface Dictionary { key: T; value: U; } let dict: Dictionary = { key: "edad", value: 30 }; ``` ## Clases Genericas ### Sintaxis Basica ```typescript class DataStore { private data: T[] = []; add(item: T): void { this.data.push(item); } getAll(): T[] { return [...this.data]; } getByIndex(index: number): T | undefined { return this.data[index]; } } let stringStore = new DataStore(); stringStore.add("hola"); stringStore.add("mundo"); ``` ### Clase Generica con Multiples Parametros de Tipo ```typescript class Pair { constructor( public key: K, public value: V ) {} toString(): string { return `${this.key}: ${this.value}`; } } let pair = new Pair("edad", 30); pair.toString(); // "edad: 30" ``` ## Restricciones de Genericos ### Usando extends ```typescript interface HasLength { length: number; } function logLength(arg: T): T { console.log(arg.length); return arg; } logLength("hola"); // 5 logLength([1, 2, 3]); // 3 logLength({ length: 10 }); // 10 // logLength(123); // Error: number no tiene length ``` ### Restringir a Claves de Objetos ```typescript function getProperty(obj: T, key: K): T[K] { return obj[key]; } let person = { name: "Alice", age: 30, city: "NYC" }; getProperty(person, "name"); // string getProperty(person, "age"); // number // getProperty(person, "foo"); // Error ``` ### Multiples Restricciones ```typescript function compare( a: T, b: T ): number { return a.name.localeCompare(b.name) || a.age - b.age; } interface HasName { name: string; } interface HasAge { age: number; } ``` ## Alias de Tipos Genericos ```typescript type Result = { success: boolean; data?: T; error?: string; }; function fetchUser(): Result { return { success: true, data: user }; } ``` ## Parametros de Tipo por Defecto ```typescript interface Response { data: T; status: number; } let r1: Response = { data: "OK", status: 200 }; let r2: Response = { data: 42, status: 200 }; ``` ## Tipos de Utilidad Genericos ### Partial Todas las propiedades opcionales: ```typescript interface User { name: string; age: number; } function updateUser(id: number, updates: Partial): User { // Combinar actualizaciones con usuario existente return { ...existingUser, ...updates }; } ``` ### Required Todas las propiedades requeridas: ```typescript interface Config { host?: string; port?: number; } let partial: Partial = { host: "localhost" }; let full: Required = { host: "localhost", port: 8080 }; ``` ### Pick Seleccionar propiedades: ```typescript interface User { id: number; name: string; email: string; age: number; } type UserPreview = Pick; // { id: number; name: string } ``` ### Omit Excluir propiedades: ```typescript type UserWithoutEmail = Omit; // { id: number; name: string; age: number } ``` ### Record Crear tipo de objeto: ```typescript type Role = "admin" | "user" | "guest"; type Permissions = Record; let perms: Permissions = { admin: true, user: false, guest: true }; ``` ### Exclude Excluir de union: ```typescript type T = "a" | "b" | "c"; type U = Exclude; // "b" | "c" ``` ### Extract Extraer de union: ```typescript type T = "a" | "b" | "c"; type U = Extract; // "a" | "b" ``` ### NonNullable Eliminar null y undefined: ```typescript type T = string | null | undefined; type U = NonNullable; // string ``` ### ReturnType Obtener tipo de retorno de funcion: ```typescript function createUser() { return { name: "Alice", age: 30 }; } type User = ReturnType; // { name: string; age: number } ``` ### Parameters Obtener parametros de funcion: ```typescript function greet(name: string, age: number): string { return `Hola, ${name}, edad ${age}`; } type GreetParams = Parameters; // [name: string, age: number] ``` ## Generico con new() ```typescript function create(constructor: new () => T): T { return new constructor(); } class User { name: string = "Por defecto"; } let user = create(User); ``` ## Generico en Tipos Condicionales ```typescript type IsArray = T extends any[] ? true : false; type A = IsArray; // true type B = IsArray; // false ``` ## Resumen - Los genericos preservan la informacion de tipo - `` es el nombre de parametro de tipo mas comun - Usar `extends` para restringir tipos genericos - Funciones genericas: `function foo(x: T): T` - Interfaces genericas: `interface Container` - Clases genericas: `class Box` - Tipos de utilidad incorporados: Partial, Pick, Omit, Record - Usar multiples parametros de tipo: ``

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →