Publicado por Ignacio Figueroa el martes, 18 de noviembre de 2025
Utility Types en TypeScript: los trucos que te salvan la vida (y el código)
Una guía rápida y práctica de los Utility Types de TypeScript, explicados con ejemplos simples y sin vueltas, para escribir menos código y tipar mucho mejor.
Si usás TypeScript todos los días, seguramente ya te cruzaste con cosas como Partial, Pick, Omit o Record.
Y si no, tranqui: te estás perdiendo joyitas que te hacen escribir menos código y evitar quilombos innecesarios.
Los Utility Types son como esos atajos que te sabés en el teclado y te cambian la vida. No son magia, pero te permiten transformar tipos como si fueran piezas de Lego.
En este artículo te muestro los más útiles (los que realmente vas a usar), explicados sin vueltas y con ejemplos claros.
Partial<T> — Hacé que todas las propiedades sean opcionales
Cuando tenés un objeto gigante y querés permitir actualizaciones parciales, este tipo te salva.
Antes (dolor):
type UserUpdate = {name?: string;email?: string;age?: number;};
Después (felicidad):
type User = {name: string;email: string;age: number;};type UserUpdate = Partial<User>;
Listo. Nada más que decir.
Lo que era un embole pasa a ser una línea.
Required<T> — Lo contrario de Partial
Convierte TODAS las propiedades en obligatorias.
type User = {name?: string;email?: string;};type StrictUser = Required<User>;
Ahora StrictUser te obliga a mandar todo.
Muy útil para validaciones internas donde no querés medias tintas.
Readonly<T> — Evitá que te rompan el objeto
Ideal cuando no querés que un objeto cambie nunca más.
type Config = {apiKey: string;theme: string;};const config: Readonly<Config> = {apiKey: "123",theme: "dark",};config.theme = "light"; // ❌ Error
Perfecto para configuraciones que no deberían mutar.
Pick<T, K> — Elegí solo las propiedades que te sirven
Imaginá que tenés un tipo enorme, pero necesitás solo 2 campos.
Antes armabas otro tipo a mano… pero no hace falta.
type User = {id: string;name: string;email: string;age: number;};type UserPreview = Pick<User, "id" | "name">;
Boom. Solo lo que necesitás. Nada más.
Omit<T, K> — Todo menos esto
Es el “anti Pick”.
type UserWithoutEmail = Omit<User, "email">;
Muy útil cuando querés mandar un objeto al frontend sin exponer algo sensible.
Record<K, T> — Tu colección tipada, sin dolor de cabeza
Si querés un objeto tipo diccionario, este es EL utility type.
type Roles = "admin" | "user" | "guest";const permissions: Record<Roles, boolean> = {admin: true,user: true,guest: false,};
Con esto evitás:
- claves mal escritas
- valores faltantes
- estructura inconsistente
Exclude<T, U> — Eliminá tipos de una unión
type Status = "loading" | "success" | "error";type WithoutError = Exclude<Status, "error">;
Extract<T, U> — Lo opuesto: quedate solo con los compatibles
type OnlyErrors = Extract<Status, "error">;
NonNullable<T> — Chau null, chau undefined
type MaybeString = string | null | undefined;type SafeString = NonNullable<MaybeString>; // solo string
Esto reduce MUCHOS bugs, especialmente en funciones.
¿Por qué usar Utility Types?
Porque escribir tipos a mano es:
- repetitivo
- propenso a errores
- un embole
Y TypeScript ya te da todo hecho.
Lo mejor es que combinan entre sí, por ejemplo:
type UserSafePreview = Readonly<Pick<User, "id" | "name">>;
Tipo pequeño, seguro y sin mutaciones.
Perfecto.
Conclusión
Los Utility Types son una de esas cosas que ignorás hasta que las usás… y después no querés vivir sin ellas.
Te hacen escribir menos, equivocarte menos y pensar más en la lógica y menos en la burocracia del tipado.
Si usás TypeScript y no estás metiendo estos utilities en tu día a día… amigo, te estás complicando solo.
Comunidad (0)
Aún no hay reflexiones aquí...