CodeForge

TypeScript de Cero a Experto / Utility types

Pick y Omit: seleccionar y excluir campos

Teoría18 min20 XP

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:

pick.ts
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:

omit.ts
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.