Los utility types son tipos genéricos integrados en TypeScript que convierten un tipo en otro. En lugar de escribir un segundo tipo User con todos los campos opcionales, escribes Partial<User>; en lugar de copiar tres campos, Pick<User, "id" | "name">. Son globales, así que no hace falta importarlos.
Cuando User cambia, los cuatro tipos derivados lo siguen. La librería estándar de TypeScript (lib.es5.d.ts) declara 22 utility types. Las secciones siguientes los recogen todos, agrupados según el tipo de tipo con el que trabajan, con un enlace a la página detallada cuando la hay.
Tipos objeto: Partial, Required, Readonly, Pick, Omit, Record
| Utility type | Qué hace | Ejemplo |
|---|---|---|
Partial<T> | hace opcionales todas las propiedades | Partial<User> para los datos de una actualización |
Required<T> | hace obligatorias todas las propiedades (quita ?) | Required<Config> después de aplicar los valores por defecto |
Readonly<T> | hace readonly todas las propiedades | Readonly<State> |
Pick<T, K> | conserva solo las claves K | Pick<User, "id" | "name"> |
Omit<T, K> | quita las claves K | Omit<User, "password"> |
Record<K, V> | un tipo objeto con claves K y valores V | Record<"en" | "de", string> |
Required<T> es lo contrario de Partial<T>; la página de Partial trata los dos, incluido el undefined explícito que deja pasar un spread como este.
Tipos unión: Exclude, Extract, NonNullable
| Utility type | Qué hace | Ejemplo |
|---|---|---|
Exclude<U, M> | quita los miembros de la unión que se pueden asignar a M | Exclude<"a" | "b" | "c", "a"> es "b" | "c" |
Extract<U, M> | conserva los miembros de la unión que se pueden asignar a M | Extract<string | number, number> es number |
NonNullable<T> | quita null y undefined | NonNullable<string | null> es string |
Estos tres trabajan sobre uniones, no sobre objetos. Esa es la diferencia clave con Pick y Omit, que reciben un tipo objeto y una lista de sus claves.
Tipos de funciones y clases: Parameters, ReturnType y más
| Utility type | Qué hace | Ejemplo |
|---|---|---|
ReturnType<F> | el tipo de retorno de un tipo función | ReturnType<typeof createStore> |
Parameters<F> | los tipos de los parámetros como una tupla | Parameters<typeof fetchPage>[0] |
ConstructorParameters<C> | los parámetros del constructor de una clase como una tupla | ConstructorParameters<typeof Point> |
InstanceType<C> | el tipo de la instancia que crea un constructor | InstanceType<typeof Point> |
ThisParameterType<F> | el tipo del parámetro this de una función | ThisParameterType<typeof greet> |
OmitThisParameter<F> | el tipo función sin su parámetro this | el tipo de greet.bind(obj) |
ThisType<T> | fija el tipo de this dentro de los métodos de un objeto literal | se usa con noImplicitThis en APIs tipo builder |
NoInfer<T> | impide que un parámetro de tipo se infiera desde esta posición | fallback: NoInfer<C> |
typeof createOrder hace falta porque estos utility types reciben un tipo, y createOrder es un valor. Con las clases pasa lo mismo: typeof Point es el tipo del constructor, mientras que Point a secas como tipo ya significa el tipo de la instancia.
NoInfer controla de dónde saca su tipo un genérico:
Sin NoInfer, TypeScript inferiría C a partir de los dos argumentos y lo ampliaría a "red" | "green" | "blue", así que aceptaría la errata del valor por defecto.
Tipos de strings: Uppercase, Lowercase, Capitalize, Uncapitalize
| Utility type | Qué hace | Ejemplo |
|---|---|---|
Uppercase<S> | pasa a mayúsculas un tipo literal de string | Uppercase<"get"> es "GET" |
Lowercase<S> | lo pasa a minúsculas | Lowercase<"GET"> es "get" |
Capitalize<S> | pone en mayúscula el primer carácter | Capitalize<"name"> es "Name" |
Uncapitalize<S> | pone en minúscula el primer carácter | Uncapitalize<"Name"> es "name" |
Estos cuatro están integrados en el compilador en lugar de estar escritos en TypeScript, y son más útiles dentro de los template literal types, como `on${Capitalize<E>}` para nombres de handlers de eventos.
Promesas: Awaited
| Utility type | Qué hace | Ejemplo |
|---|---|---|
Awaited<T> | el tipo que obtienes con await, desenvolviendo promesas anidadas | Awaited<Promise<Promise<number>>> es number |
Awaited<ReturnType<typeof fn>> es la forma estándar de nombrar el tipo del resultado de una función async sin declararlo aparte.
Combinar utility types
Los utility types se anidan. Algunas combinaciones aparecen tan a menudo que vale la pena sabérselas de memoria:
Un utility type anidado se lee de dentro hacia fuera: Readonly<Pick<Post, "id" | "title">> primero conserva dos propiedades y luego las hace de solo lectura. Con las mismas piezas se construye un helper PartialBy que hace opcionales solo algunas claves; la página de Partial lo desarrolla.
Los utility types no hacen nada en ejecución
Todos los utility types se borran al compilar. Un valor tipado como Omit<User, "password"> puede seguir llevando una contraseña en ejecución si el objeto del que salió la tenía:
El tipo solo limita lo que tu código puede leer. Para quitar un campo de los datos, sácalo con una desestructuración como en las últimas líneas, y para impedir modificaciones en ejecución usa Object.freeze, no Readonly. Los tipos integrados son mapped types y conditional types de una línea, así que con las mismas herramientas puedes escribir los tuyos.
Preguntas frecuentes
¿Qué son los utility types en TypeScript?
Tipos genéricos que vienen con TypeScript y transforman otros tipos: Partial<T> hace opcionales todas las propiedades, Pick<T, K> conserva algunas propiedades, ReturnType<F> obtiene el tipo de retorno de una función, etc. Están declarados en la librería estándar, así que los usas sin importar nada.
¿Tengo que importar los utility types?
No. Partial, Omit, Record, ReturnType y los demás son tipos globales de los archivos de librería integrados en TypeScript. Escribe Partial<User> donde quieras; no hace falta ningún import ni ningún paquete npm.
¿Qué utility types trae TypeScript?
22, todos declarados en lib.es5.d.ts: Partial, Required, Readonly, Pick, Omit, Record, Exclude, Extract, NonNullable, Parameters, ConstructorParameters, ReturnType, InstanceType, ThisParameterType, OmitThisParameter, ThisType, NoInfer, Awaited, Uppercase, Lowercase, Capitalize y Uncapitalize.
¿Los utility types cambian los objetos en tiempo de ejecución?
No. Solo describen tipos y se borran del JavaScript de salida. Omit<User, "password"> no elimina ninguna propiedad password, y Readonly<T> no congela nada. Para cambiar el objeto real, escribe el código: una desestructuración con rest, Object.freeze, etc.
¿Puedo escribir mis propios utility types?
Sí. Los integrados son TypeScript normal: la mayoría son mapped types o conditional types de una línea en lib.es5.d.ts. type Nullable<T> = { [K in keyof T]: T[K] | null } es un utility type propio escrito de la misma forma.