Entrada / 13 feb. 2026

Utility Types de TypeScript: Partial, Omit y Pick en código real

Por qué `Partial`, `Omit` y `Pick` ayudan a eliminar interfaces duplicadas, mantener una sola fuente de verdad y volver mucho más seguros los refactors en TypeScript.

Utility Types de TypeScript: Partial, Omit y Pick en código real

👉 Ver en YouTube

Llega un punto en el que una interfaz User aparentemente limpia termina convertida en tres o cuatro tipos casi idénticos.

Uno para crear. Uno para actualizar. Uno para exponer datos públicos. Otro para vistas previas. Y, sin darte cuenta, terminas copiando la misma estructura una y otra vez solo para volver campos opcionales, ocultar un par de propiedades o quedarte con los dos valores que un componente realmente necesita.

Ese es exactamente el problema que este video resuelve con tres de las utility types más prácticas de TypeScript: Partial, Omit y Pick.

El problema real no es escribir tipos más rápido

Al principio, las interfaces duplicadas no parecen peligrosas.

Incluso se sienten explícitas.

Pero en cuanto el modelo base cambia, cada tipo copiado se convierte en un riesgo de mantenimiento.

Eso normalmente significa:

  • campos que se desalinean con el tiempo
  • refactors que dejan una variante del contrato sin actualizar
  • autocompletado menos confiable
  • cambios pequeños que se convierten en ediciones repetitivas

Por eso importan las utility types.

No son solo atajos.

Te permiten mantener una sola fuente de verdad y derivar las variantes que de verdad necesitas.

Partial<T> encaja muy bien en payloads de actualización

El primer ejemplo del video es el clásico DTO de update.

Empiezas con algo así:

interface User {
  id: string;
  name: string;
  email: string;
  avatar: string;
}

Luego necesitas actualizar solo algunos campos, así que la tentación natural es crear otra interfaz a mano.

interface UpdateUser {
  name?: string;
  email?: string;
  avatar?: string;
}

Funciona, pero ahora el contrato está duplicado.

Partial<User> te da el mismo comportamiento de campos opcionales sin reescribir la estructura.

function updateUser(id: string, changes: Partial<User>) {
  // ...
}

Y eso importa porque TypeScript ya no está adivinando.

Sabe que ese payload de actualización es un subconjunto de User.

Si el tipo base cambia, el tipo derivado sigue alineado.

Este es uno de los ejemplos más claros de mantenimiento asistido por el compilador: cambias un modelo y el contrato derivado cambia con él.

Partial es potente, pero es superficial

Aquí vale la pena ampliar una idea más allá del video.

Partial<T> solo vuelve opcionales las propiedades del primer nivel. No hace opcionales de forma recursiva los objetos anidados.

interface User {
  name: string;
  settings: {
    theme: string;
    locale: string;
  };
}

type UserPatch = Partial<User>;

En UserPatch, settings es opcional, pero si lo envías, TypeScript sigue esperando el objeto interno completo.

Muchas veces ese es el comportamiento correcto. Mantiene los patches honestos.

Pero si tu API admite actualizaciones parciales profundas, puede que necesites un tipo de dominio aparte o un helper de DeepPartial bien pensado, en lugar de asumir que Partial resuelve todos los escenarios.

Omit<T, K> define qué no debe cruzar el límite

El siguiente ejemplo del video elimina campos como id y createdAt de un tipo derivado.

Ahí es donde Omit deja de ser simple comodidad.

interface User {
  id: string;
  name: string;
  email: string;
  createdAt: Date;
}

type UserProfile = Omit<User, "id" | "createdAt">;

Ahora la forma pública o editable puede seguir conectada a User sin exponer propiedades que el consumidor no debería asignar.

Esto es especialmente útil en los límites de una API.

Te permite modelar la diferencia entre:

  • lo que guarda la base de datos
  • lo que el cliente puede enviar
  • lo que la interfaz puede mostrar

Todo sin dejar de usar el modelo original como fuente de verdad.

Pick<T, K> suele ser el contrato público más seguro

El video cierra con Pick, usando una estructura ligera como name y avatar para una vista previa.

type UserPreview = Pick<User, "name" | "avatar">;

Esta es una de las maneras más limpias de expresar intención en TypeScript.

El tipo no es “casi un usuario”.

Es exactamente el subconjunto que la UI o la función necesita.

Eso te da:

  • contratos más pequeños y explícitos
  • mejor autocompletado para quien consume el tipo
  • menos dependencias accidentales de campos irrelevantes
  • reutilización más simple en cards, listas y previews

En sistemas grandes, Pick muchas veces es más seguro que Omit para tipos públicos.

¿Por qué? Porque Pick funciona como una lista blanca.

Si el tipo base User gana un nuevo campo sensible más adelante, Pick<User, "name" | "avatar"> no lo expone por accidente. Un tipo público basado en Omit sí podría hacerlo.

Estas utilidades funcionan porque TypeScript puede transformar tipos

La idea de fondo del video es que las utility types no son helpers sueltos ni magia incorporada al azar.

Son ejemplos de mapped types: formas de construir un tipo a partir de otro en lugar de reescribir todo el contrato a mano.

Por eso escalan tan bien.

No estás manteniendo varias verdades separadas. Estás codificando una relación una sola vez y dejando que TypeScript la preserve.

Ese es el mismo instinto de diseño que aparece en otros helpers como Readonly, Required y Record.

El compilador se vuelve más útil cuando tus tipos describen cómo se relacionan las estructuras, no solo cómo se ve un objeto aislado.

Las utility types no reemplazan el modelado de dominio

También hay un límite importante aquí.

No todo tipo derivado debería salir de Partial, Omit o Pick.

A veces un tipo separado sí es la abstracción correcta.

Por ejemplo:

  • las reglas de validación pueden diferir del modelo de base de datos
  • un payload de escritura puede necesitar menos campos y nombres distintos
  • una respuesta pública puede requerir valores calculados, no solo ocultar propiedades

Ahí está la línea de madurez.

Usa utility types cuando preservan el significado y eliminan duplicación. Escribe tipos de dominio explícitos cuando el contrato realmente es diferente.

La ganancia de mantenibilidad es mayor que ahorrar líneas

El video presenta las utility types como una forma de ahorrar código, y eso es cierto.

Pero el beneficio más grande es que vuelven más seguros los refactors.

Cuando tu modelo User evoluciona, los tipos derivados con Partial, Omit y Pick evolucionan con él. El autocompletado sigue siendo preciso. Las suposiciones rotas aparecen antes. Las actualizaciones manuales repetidas desaparecen.

Por eso estas utilidades se sienten tan prácticas.

No hacen que TypeScript sea más “ingenioso”.

Hacen que el sistema sea más coherente.

El takeaway

Partial, Omit y Pick son útiles porque te evitan reescribir la misma intención en varios lugares.

Te ayudan a expresar con claridad tres relaciones muy comunes:

  • una actualización es una versión parcial del modelo
  • una forma pública omite campos que no deberían salir
  • una vista previa elige solo los campos que un consumidor necesita

Eso no es solo sintaxis más limpia.

Es mejor diseño.

Y cuando empiezas a tratar tus tipos base como una fuente de verdad en lugar de una plantilla para copiar, TypeScript empieza a hacerse cargo de mucha más parte del mantenimiento.