TypeScript de Cero a Experto / Utility types
Pick y Omit: seleccionar y excluir campos
Si Partial y compañía cambian todos los campos, Pick y Omit eligen CUÁLES:
Pick se queda con las claves que nombras, Omit quita las que no quieres. Con
ellos construyes vistas parciales de tus datos —un tipo público que oculta la
contraseña, un input de creación sin el id, un resumen con dos campos—. Derivadas,
sincronizadas, sin repetir.
Recortar o tachar
Pick<T, K>: quedarte con algunas claves
Pick toma un tipo y una unión de claves, y devuelve un tipo SOLO con esas:
type Usuario = {
id: number;
nombre: string;
email: string;
passwordHash: string;
creado: Date;
};
// Pick<Usuario, "id" | "nombre"> = { id: number; nombre: string }
type UsuarioResumen = Pick<Usuario, "id" | "nombre">;
const resumen: UsuarioResumen = { id: 1, nombre: "Sara" }; // solo esos dos campos
// resumen.email; // ❌ 'email' no existe en UsuarioResumen
// caso real: una función que devuelve solo lo mínimo para una lista
function listar(usuarios: Usuario[]): Pick<Usuario, "id" | "nombre">[] {
return usuarios.map((u) => ({ id: u.id, nombre: u.nombre }));
}Pick<Usuario, "id" | "nombre"> construye un tipo nuevo con exactamente esas dos
claves y sus tipos (recuerda K extends keyof T del módulo 5 —eso es lo que hace por
dentro). Es perfecto para "vistas" reducidas: la tarjeta de un listado, el payload
mínimo de una respuesta. Y las claves se validan: pedir "telefono" (que no existe)
da error.
Omit<T, K>: quitar algunas claves
Omit es el complemento: devuelve el tipo SIN las claves que nombras. Brilla cuando
quieres quitar pocas de muchas:
type Usuario = {
id: number;
nombre: string;
email: string;
passwordHash: string;
creado: Date;
};
// el tipo PÚBLICO: todo menos el hash de la contraseña
type UsuarioPublico = Omit<Usuario, "passwordHash">;
// = { id; nombre; email; creado } — passwordHash NUNCA se expone
// el tipo para CREAR: sin id ni creado (los pone el servidor)
type UsuarioNuevo = Omit<Usuario, "id" | "creado" | "passwordHash">;
// = { nombre; email }
// una función que oculta datos sensibles al enviar al cliente:
function aPublico(u: Usuario): UsuarioPublico {
const { passwordHash, ...publico } = u; // rest para quitar el campo
return publico;
}Omit<Usuario, "passwordHash"> es un patrón de seguridad clásico: el tipo público
que garantiza, a nivel de compilación, que nunca expongas el hash de la contraseña.
Si alguien intentara devolver el campo, TS lo marcaría. Los tipos como muro de
seguridad —no solo de corrección.
Tienes type Usuario con 10 campos, uno es passwordHash. Quieres un tipo público que exponga los otros 9. ¿Cuál es más limpio, Pick u Omit?
Mini-reto
Construye vistas: 1) define type Pedido = { id: number; cliente: string; total: number; tarjeta: string; notas: string }; 2) crea type PedidoPublico = Omit<Pedido, "tarjeta"> (oculta el número de tarjeta) y type PedidoResumen = Pick<Pedido, "id" | "total"> (para una lista); 3) escribe una función que convierta
un Pedido en PedidoPublico usando destructuring con rest. Sientes cómo Pick y
Omit esculpen vistas seguras de un mismo dato.
Qué sigue
Modificar y seleccionar campos, dominado. El siguiente utility type construye tipos
desde cero: Record<K, V> —un objeto con claves de tipo K y valores de tipo V—,
el que ya usaste de refilón para los totales por categoría. Ahora lo entiendes a
fondo.