Generics
Los generics son como plantillas de tipo. Imagina que quieres una función que devuelva el primer elemento de un array, pero funcione con arrays de cualquier tipo: números, strings, objetos. Sin generics tendrías que escribir una versión por cada tipo, o usar any (perdiendo toda seguridad).
Con generics, defines un "parámetro de tipo" (T) que se resuelve cuando usas la función: el compilador infiere automáticamente qué tipo es T según lo que le pases.
Los constraints (restricciones) con extends limitan qué tipos puede ser T. Por ejemplo, T extends { id: string } garantiza que T siempre tendrá una propiedad id de tipo string, permitiéndote acceder a ella sin errores.
El patrón K extends keyof T es especialmente poderoso: garantiza que K es una clave válida de T, y T[K] devuelve exactamente el tipo de esa propiedad. Los generics son la base de todas las librerías TypeScript populares: useState<T>, Array<T>, Promise<T>.
// Función genérica básica
function primero<T>(arr: T[]): T | undefined {
return arr[0];
}
const num = primero([1, 2, 3]); // T = number
const str = primero(["a", "b"]); // T = string
// Constraints — T debe tener ciertas propiedades
function obtenerPropiedad<T, K extends keyof T>(obj: T, clave: K): T[K] {
return obj[clave];
}
const nombre = obtenerPropiedad({ nombre: "Ana", edad: 25 }, "nombre"); // string
const edad = obtenerPropiedad({ nombre: "Ana", edad: 25 }, "edad"); // number
// obtenerPropiedad({ nombre: "Ana" }, "email"); // Error: "email" no existe
// Clase genérica
class Pila<T> {
private items: T[] = [];
push(item: T): void { this.items.push(item); }
pop(): T | undefined { return this.items.pop(); }
peek(): T | undefined { return this.items.at(-1); }
get size(): number { return this.items.length; }
}
const pilaNumeros = new Pila<number>();
pilaNumeros.push(1); pilaNumeros.push(2);
const top = pilaNumeros.pop(); // number | undefined
// Interface genérica — ApiResponse
interface ApiResponse<T> {
data: T;
status: number;
timestamp: string;
error?: string;
}
type UsuariosResponse = ApiResponse<Usuario[]>;
type LoginResponse = ApiResponse<{ token: string; expires: number }>;
Practica esta lección
Resuelve los ejercicios del curso de TypeScript en la app, gratis y con corrección automática.
Empezar a practicar