Aquí es donde TypeScript deja de ser “JavaScript con tipos” y se convierte en un superpoder. Hasta ahora hemos definido tipos manualmente. Pero, ¿y si pudiéramos generar los tipos automáticamente desde nuestro código?
typeof: Extrayendo el ADN
En JS, typeof devuelve un string (“string”, “number”, “object”).
En TS, si lo usamos en un contexto de tipos, devuelve el tipo completo.
const settings = {
theme: "dark",
notifications: true,
version: 1.0
};
// En vez de escribir la interfaz manualmente...
// type Settings = { theme: string; notifications: boolean; version: number }; 😴
type Settings = typeof settings;
// 🪄 ¡Boom! TS acaba de escribir la interfaz por ti.const settings = {
theme: "dark",
notifications: true,
version: 1.0
};
// En vez de escribir la interfaz manualmente...
// type Settings = { theme: string; notifications: boolean; version: number }; 😴
type Settings = typeof settings;
// 🪄 ¡Boom! TS acaba de escribir la interfaz por ti.Esto es brutal para APIs o librerías de terceros (o nuestras propias constantes de configuración). Tenemos una “Single Source of Truth” (Fuente Única de Verdad): el valor. El tipo se adapta solo.
Truco para APIs
Imagina que tienes la respuesta JSON de una API. En lugar de escribir la interfaz a mano, puedes pegar el JSON como una constante (mock) y sacar el tipo de ahí. Así, el ejemplo sirve de documentación y de generador de tipos a la vez.
keyof: Dame las llaves
keyof toma un Tipo y nos devuelve una Unión de sus claves (keys).
interface Usuario {
name: string;
age: number;
email: string;
}
type UsuarioKeys = keyof Usuario;
// Es equivalente a: "name" | "age" | "email"interface Usuario {
name: string;
age: number;
email: string;
}
type UsuarioKeys = keyof Usuario;
// Es equivalente a: "name" | "age" | "email"¿Para qué sirve? Para que no podamos pedir propiedades que no existen.
function getProperty(user: Usuario, key: keyof Usuario) {
return user[key];
}
const me: Usuario = { name: "Paco", age: 39, email: "..." };
getProperty(me, "name"); // ✅
getProperty(me, "password"); // ❌ Error: Argument of type '"password"' is not assignable...function getProperty(user: Usuario, key: keyof Usuario) {
return user[key];
}
const me: Usuario = { name: "Paco", age: 39, email: "..." };
getProperty(me, "name"); // ✅
getProperty(me, "password"); // ❌ Error: Argument of type '"password"' is not assignable...El Combo Definitivo: keyof typeof
Esta es una de las combinaciones más usadas en TypeScript real. Se usa cuando queremos sacar los keys de un objeto/valor que ya existe (no de una interfaz).
typeof objeto-> Nos da el Tipo del objeto.keyof (Tipo)-> Nos da las keys de ese Tipo.
const COLORES = {
rojo: "#FF0000",
verde: "#00FF00",
azul: "#0000FF"
} as const; // 'as const' hace que sean literales y readonly
// Queremos un tipo que solo permita "rojo" | "verde" | "azul"
type NombreColor = keyof typeof COLORES;
function pintar(color: NombreColor) { ... }
pintar("rojo"); // ✅
pintar("amarillo"); // ❌const COLORES = {
rojo: "#FF0000",
verde: "#00FF00",
azul: "#0000FF"
} as const; // 'as const' hace que sean literales y readonly
// Queremos un tipo que solo permita "rojo" | "verde" | "azul"
type NombreColor = keyof typeof COLORES;
function pintar(color: NombreColor) { ... }
pintar("rojo"); // ✅
pintar("amarillo"); // ❌Nota Pro
El as const es vital aquí. Si no lo ponemos, TS inferirá que propiedades son string, y typeof será muy genérico. Con as const le decimos: “¡Esto no cambia, es literal!”.
¡Probémoslo!
Usemos el editor. Creemos un objeto config con varias opciones. Usemos typeof para sacar su tipo y creemos una función que reciba ese tipo.
En la Parte 6 veremos los Generics, la herramienta que nos permite crear componentes y funciones reutilizables que funcionan con cualquier tipo (el famoso <T>).