Lección 91: keyof, typeof y Lookup Types
🎯 Objetivo: Dominar los operadores keyof, typeof y los lookup types (acceso indexado) para crear tipos derivados de forma dinámica.
🧠 Concepto
1. keyof — Operador de claves
Section titled “1. keyof — Operador de claves”keyof toma un tipo y devuelve una unión de sus claves (nombres de propiedades).
💻 Ejemplo
type Persona = { nombre: string; edad: number; email: string;};
type ClavesPersona = keyof Persona;// ⚡ "nombre" | "edad" | "email"
const k1: ClavesPersona = "nombre"; // ✅const k2: ClavesPersona = "edad"; // ✅const k3: ClavesPersona = "apellido"; // ❌ ErrorEsto es increíblemente útil para restringir qué valores puede tomar un parámetro a las claves reales de un tipo.
keyof con genéricos
Section titled “keyof con genéricos”function obtenerPropiedad<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key];}
const persona: Persona = { nombre: "Ana", edad: 30, email: "ana@mail.com" };const nombre = obtenerPropiedad(persona, "nombre"); // stringconst edad = obtenerPropiedad(persona, "edad"); // number// obtenerPropiedad(persona, "apellido"); // ❌ Error: no es clave de Persona🧠 Aplicación real: APIs de acceso seguro a propiedades, validación de formularios, selectores de estado.
2. typeof — Obtener tipo de un valor
Section titled “2. typeof — Obtener tipo de un valor”typeof en TypeScript (en contexto de tipo) captura el tipo de una variable o expresión en tiempo de compilación.
const config = { api: "https://api.example.com", timeout: 5000, retries: 3,};
type TipoConfig = typeof config;// {// api: string;// timeout: number;// retries: number;// }
function iniciar(cfg: TipoConfig) { /* ... */ }iniciar({ api: "...", timeout: 2000, retries: 1 }); // ✅⚠️ No confundir con el typeof de JavaScript (que evalúa en tiempo de ejecución). En contexto de tipo, TypeScript lo interpreta en compilación.
typeof con funciones
Section titled “typeof con funciones”function sumar(a: number, b: number): number { return a + b;}
type TipoSumar = typeof sumar;// (a: number, b: number) => number
type RetornoSumar = ReturnType<typeof sumar>;// number
type ParametrosSumar = Parameters<typeof sumar>;// [a: number, b: number]3. Lookup Types — Acceso indexado Tipo['propiedad']
Section titled “3. Lookup Types — Acceso indexado Tipo['propiedad']”También llamados indexed access types. Permiten acceder al tipo de una propiedad específica usando la sintaxis de corchetes.
type Persona = { nombre: string; direccion: { calle: string; ciudad: string; }; hobbies: string[];};
type TipoNombre = Persona["nombre"]; // stringtype TipoDireccion = Persona["direccion"]; // { calle: string; ciudad: string }type TipoHobbies = Persona["hobbies"]; // string[]type TipoItemHobby = Persona["hobbies"][number]; // string (acceso a item del array)Lookup types con uniones de claves
Section titled “Lookup types con uniones de claves”type Persona = { nombre: string; edad: number; activo: boolean };
type NombreOEdad = Persona["nombre" | "edad"];// string | number
type CualquierValor = Persona[keyof Persona];// string | number | booleanLookup types anidados
Section titled “Lookup types anidados”type RespuestaAPI = { data: { usuario: { id: number; perfil: { avatar: string; bio: string; }; }; };};
type BioUsuario = RespuestaAPI["data"]["usuario"]["perfil"]["bio"];// string4. Aplicaciones prácticas combinadas
Section titled “4. Aplicaciones prácticas combinadas”Eventos tipados
Section titled “Eventos tipados”type Eventos = { click: { x: number; y: number }; keydown: { key: string }; submit: { formData: FormData };};
function emitirEvento<E extends keyof Eventos>( evento: E, datos: Eventos[E]) { console.log(`Evento ${evento}:`, datos);}
emitirEvento("click", { x: 10, y: 20 }); // ✅emitirEvento("keydown", { key: "Enter" }); // ✅emitirEvento("click", { key: "x" }); // ❌ Error: no coincide con clickTipos derivados de objetos existentes
Section titled “Tipos derivados de objetos existentes”const colores = { primary: "#007bff", secondary: "#6c757d", success: "#28a745", danger: "#dc3545",} as const;
type ColorKey = keyof typeof colores;// "primary" | "secondary" | "success" | "danger"
type ColorValue = typeof colores[ColorKey];// "#007bff" | "#6c757d" | "#28a745" | "#dc3545"📝 Resumen: keyof extrae claves como unión, typeof captura tipos de valores existentes, y los lookup types permiten navegar por la estructura de tipos. Combinados, permiten escribir código genérico y reutilizable con type safety absoluto.