¿Qué utility types de TypeScript conoces y para qué sirven?
Ver respuesta — intenta responderla en voz alta primero
Son tipos genéricos incluidos en TypeScript que transforman tipos existentes en lugar de duplicarlos: Partial hace todo opcional, Pick y Omit seleccionan o quitan propiedades, Record construye objetos clave-valor y ReturnType extrae el tipo de retorno de una función.
La idea central: define tu tipo base una vez y deriva las variantes. Si mañana el tipo base cambia, todas las variantes se actualizan solas.
Los más usados:
Partial<T>: todas las propiedades pasan a ser opcionales. Perfecto para funciones de actualización donde solo mandas los campos que cambian.Required<T>es lo contrario: todas obligatorias.Pick<T, K>: nuevo tipo solo con las propiedades que elijas.Omit<T, K>: nuevo tipo sin las propiedades que indiques. Típico: quitaridycreadoEnpara el formulario de creación.Record<K, V>: objeto cuyas claves sonKy cuyos valores sonV. Muy útil con uniones de literales como claves.ReturnType<F>: extrae el tipo que devuelve una función, sin escribirlo a mano.
La señal para usarlos: cuando estés a punto de copiar y pegar un tipo cambiándole dos cosas.
interface Usuario {
id: number;
nombre: string;
email: string;
rol: "admin" | "usuario";
}
// Partial: actualizar solo algunos campos
function actualizarUsuario(id: number, cambios: Partial<Usuario>): void {
console.log(`Actualizando ${id}`, cambios);
}
actualizarUsuario(1, { nombre: "Ana María" }); // no exige el resto
// Pick: solo lo necesario para una tarjeta de perfil (nombre + email)
type TarjetaPerfil = Pick<Usuario, "nombre" | "email">;
// Omit: el formulario de alta no tiene id todavía
type NuevoUsuario = Omit<Usuario, "id">;
const alta: NuevoUsuario = { nombre: "Luis", email: "luis@mail.com", rol: "usuario" };
// Record: un diccionario tipado de permisos por rol
type Permisos = Record<Usuario["rol"], string[]>;
// Si falta un rol o sobra una clave, no compila
const permisos: Permisos = { admin: ["leer", "borrar"], usuario: ["leer"] };
// ReturnType: reutilizar el tipo que devuelve una función
function crearSesion(usuario: Usuario) {
return { token: "abc123", usuario, expira: Date.now() + 3600 };
}
// Sesion = { token: string; usuario: Usuario; expira: number }
type Sesion = ReturnType<typeof crearSesion>;
Duplicar el tipo a mano en lugar de derivarlo:
// (usa la interface Usuario del ejemplo anterior)
// Duplicado: si Usuario cambia, esto queda desincronizado en silencio
interface UsuarioEditableMal {
nombre?: string;
email?: string;
rol?: "admin" | "usuario";
}
// Derivado: se actualiza solo cuando Usuario cambia
type UsuarioEditable = Partial<Omit<Usuario, "id">>;
El problema del duplicado no es escribirlo hoy, es mantenerlo mañana: alguien añade un campo a Usuario y la copia manual no se entera.
"Los utility types son transformadores de tipos que trae TypeScript para no duplicar definiciones. Los que más uso:
Partialpara funciones de actualización donde solo mando los campos que cambian,Omitpara variantes como 'usuario sin id' en formularios de creación,Pickcuando un componente solo necesita dos o tres propiedades,Recordpara diccionarios tipados yReturnTypepara extraer lo que devuelve una función. La ventaja es el mantenimiento: defino el tipo base una vez y las variantes se actualizan solas cuando cambia."
Con la interfaz Usuario del ejemplo: 1) define VistaPublica con solo nombre y rol; 2) define BorradorUsuario donde todo es opcional excepto que no incluye id; 3) define UsuariosPorEmail, un diccionario de string a Usuario.
Ver solución
interface Usuario {
id: number;
nombre: string;
email: string;
rol: "admin" | "usuario";
}
// 1) Solo dos propiedades
type VistaPublica = Pick<Usuario, "nombre" | "rol">;
// 2) Sin id y todo opcional: se pueden combinar utility types
type BorradorUsuario = Partial<Omit<Usuario, "id">>;
// 3) Diccionario clave string -> Usuario
type UsuariosPorEmail = Record<string, Usuario>;
const vista: VistaPublica = { nombre: "Ana", rol: "admin" };
const borrador: BorradorUsuario = { nombre: "Luis" };