Tipos de utilidad de TypeScript — Los que vale la pena memorizar (y los demás)
Parcial, Elegir, Omitir, Registrar, TipoDeRetorno, Parámetros, Esperado — ocho tipos útiles con ejemplos antes y después y una opinión honesta sobre cuáles usarás cada semana.
Probablemente hayas leído una página de documentación de TypeScript que lista más de 20 tipos útiles en orden alfabético, define cada uno en una oración y te deja preguntándote cuáles de ellos es necesario internalizar y cuáles existen para personas que escriben código interno de marcos. Esta es la versión más honesta: ocho tipos, ejemplos concretos antes y después, y una respuesta directa sobre su uso diario versus su uso ocasional.
Si empiezas desde JSON bruto y aún no has escrito tus interfaces, convertidor de JSON a TypeScript te llevará a una interfaz básica en segundos — luego vuelve aquí para aplicar estos tipos útiles encima.
Partial — Uso semanal. Aprende primero.
Hace que cada propiedad en T sea opcional. El caso canónico es actualizaciones en estilo PATCH, donde solo se envían los campos que cambiaron.
// Before: manually duplicating the interface with optional versions of everything
interface UserUpdate {
name?: string;
email?: string;
age?: number;
}
// After: Partial derives it from the source of truth
interface User {
name: string;
email: string;
age: number;
}
function updateUser(id: string, updates: Partial<User>) {
// updates.name is string | undefined — TypeScript knows
}
El problema con la versión «antes»: si añades un campo a User, debes recordar añadirlo también a UserUpdate . Con Partial<User>, añadir un campo a la interfaz de origen lo hace disponible automáticamente en las actualizaciones. Los tipos permanecen sincronizados.
Required — Uso mensual, pero te salva en una situación específica.
El inverso de Partial — elimina todas las ? de un tipo. Más útil después de la validación: recibes un objeto de configuración de tipo suelto, validas que todos los campos estén presentes y luego quieres que TypeScript deje de sugerir que todo podría ser indefinido.
// Before: after validating, you still fight undefined checks everywhere
interface Config {
apiUrl?: string;
timeout?: number;
retries?: number;
}
function initApp(config: Config) {
config.apiUrl?.trim(); // need optional chaining even after checking
}
// After: Required signals "this has been validated, stop warning me"
function validateAndInit(raw: Config): void {
if (!raw.apiUrl) throw new Error("apiUrl required");
if (!raw.timeout) throw new Error("timeout required");
if (!raw.retries) throw new Error("retries required");
const config = raw as Required<Config>;
config.apiUrl.trim(); // no optional chaining needed
}
Nota honesta: Required<T> no realiza validación en tiempo de ejecución — aún necesitas escribir las comprobaciones. Solo cambia lo que TypeScript cree en el nivel de tipos. Usa esto para comunicar «este objeto ya ha sido validado» al nivel de tipos.
Pick — Uso semanal. Elige lo que necesitas.
Crea un nuevo tipo que contenga solo las propiedades que nombras de T. Útil cuando necesitas un subconjunto de una interfaz más grande — formas de API pública, modelos de vista, respuestas serializadas.
// Before: manually maintaining a separate interface that drifts from User
interface UserPublicProfile {
name: string;
bio: string;
avatarUrl: string;
}
// After: Pick stays in sync with the source
interface User {
id: string;
name: string;
email: string; // private — shouldn't go to clients
passwordHash: string; // definitely private
bio: string;
avatarUrl: string;
}
type UserPublicProfile = Pick<User, "name" | "bio" | "avatarUrl">;
Pick es la herramienta adecuada cuando la lista de propiedades que quieres es más corta que la lista que necesitas exclude. Cuando el caso se invierte, busca Omit.
Omit — Uso semanal. Elige lo que no necesitas.
Complemento de Pick — crea un tipo con todas las propiedades de T excepto las que nombras. Cuando tienes una interfaz grande y solo unos pocos campos para excluir, Omit hace más clara la intención que listar todos los campos que deseas incluir.
// Before: manually listing every field except the sensitive ones
// Easy to miss a new field added to User later
interface UserForClient {
id: string;
name: string;
email: string;
bio: string;
avatarUrl: string;
// passwordHash intentionally omitted — but a future dev might not know that
}
// After: Omit states the exclusion explicitly
type UserForClient = Omit<User, "passwordHash">;
// If User gains a new "address" field, UserForClient gets it automatically
Una cosa que ni Pick ni Omit hacen: cambiar el tipo de propiedades individuales. Si quieres seleccionar campos y y transformar sus tipos, estás buscando un tipo mapeado, que es una herramienta completamente diferente.
Record — Uso semanal. El diccionario tipado.
Crea un tipo de objeto donde todas las claves son del tipo K y todos los valores son del tipo V. La verdadera ventaja surge cuando K es un tipo de unión — TypeScript dará error si faltas una clave. Las firmas de índice generales aceptan objetos incompletos silenciosamente; Record con una clave de unión no lo hace.
// Before: index signature with no exhaustiveness checking
const rolePermissions: { [key: string]: string[] } = {
admin: ["read", "write", "delete"],
editor: ["read", "write"],
// forgot "viewer" — TypeScript doesn't notice
};
// After: Record with a union key enforces completeness
type Role = "admin" | "editor" | "viewer";
const rolePermissions: Record<Role, string[]> = {
admin: ["read", "write", "delete"],
editor: ["read", "write"],
viewer: ["read"],
// TypeScript error if any Role is missing
// TypeScript error if you try to add an unknown key
};
La comprobación de exhaustividad es la verdadera ventaja. Importa cuando las claves representan algo significativo, como roles, tipos de eventos, métodos HTTP o códigos de estado — cualquier cosa donde una ausencia de caso sea un error, no simplemente una omisión.
ReturnType — Uso semanal si consumes funciones de terceros.
Extrae el tipo de retorno de una función. Más útil cuando consumes una función de una biblioteca y quieres tipar una variable que contiene su salida — sin necesidad de importar el tipo de retorno por separado (lo que las bibliotecas no siempre exportan de forma limpia).
// Before: manually annotating the return type — it can drift
function getCurrentUser() {
return { id: "u1", name: "Alice", roles: ["admin"] as const };
}
let cachedUser: { id: string; name: string; roles: readonly string[] };
// If getCurrentUser's return changes, this annotation doesn't update automatically
// After: ReturnType derives it and keeps in sync
type CurrentUser = ReturnType<typeof getCurrentUser>;
let cachedUser: CurrentUser;
// Especially useful with unexported library types:
import { useQuery } from "@tanstack/react-query";
type QueryResult = ReturnType<typeof useQuery>;
// No need to figure out what QueryObserverResult<...> looks like or import it
Parameters — Uso ocasional. Principalmente para envolventes.
Extrae los tipos de parámetros de una función como una tupla. Vista honesta: no llegarás a usar esto semanalmente a menos que escribas muchas funciones envolventes o utilidades de orden superior. Pero cuando lo necesitas, no hay alternativa limpia.
// Before: manually duplicating parameter types in the wrapper
function createEvent(
type: string,
payload: Record<string, unknown>,
timestamp: number
) { /* ... */ }
// Every time createEvent changes, this wrapper needs a manual update:
function loggedCreateEvent(
type: string,
payload: Record<string, unknown>,
timestamp: number
) {
console.log("Creating event:", type);
return createEvent(type, payload, timestamp);
}
// After: Parameters keeps the wrapper in sync automatically
function loggedCreateEvent(...args: Parameters<typeof createEvent>) {
console.log("Creating event:", args[0]);
return createEvent(...args);
}
El patrón de expansión y resto (...args: Parameters<F>) es el idioma principal. También aparece en mocks de pruebas: jest.fn<ReturnType<F>, Parameters<F>>() te da un mock completamente tipado sin necesidad de importar la firma de la función por separado.
Awaited — Usa cuando necesitas desempaquetar tipos de Promise sin llamar a la función.
Añadido en TypeScript 4.5 (lanzado en noviembre de 2021). Desempaqueta recursivamente Promise<T> para llegar a T. Antes de que existiera, obtener el tipo resuelto de una función asíncrona implicaba escribir un tipo condicional: ReturnType<F> extends Promise<infer U> ? U : never — que falla con Promises anidadas y es difícil de leer en diferencias.
// Before: conditional type to unwrap — breaks on nested Promises
async function fetchUser(id: string) {
const res = await fetch(`/api/users/${id}`);
return res.json() as { id: string; name: string; email: string };
}
type FetchedUser =
ReturnType<typeof fetchUser> extends Promise<infer U> ? U : never;
// Works for Promise<T> but not Promise<Promise<T>>
// After: Awaited handles both cases cleanly
type FetchedUser = Awaited<ReturnType<typeof fetchUser>>;
// Awaited recursively unwraps:
type A = Awaited<Promise<string>>; // string
type B = Awaited<Promise<Promise<string>>>; // string
type C = Awaited<string>; // string (no-op on non-Promise)
La combinación Awaited<ReturnType<typeof fn>> vale la pena memorizar como unidad — cubre el 90% de la extracción de tipos asíncronos en el código de aplicaciones.
Guía rápida
| Tipo útil | Qué hace | Frecuencia de uso | Caso principal de uso |
|---|---|---|---|
Partial<T> | Todas las propiedades se vuelven opcionales | Semanalmente | Cuerpos de actualización en estilo PATCH |
Required<T> | Todas las propiedades opcionales se vuelven obligatorias | Mensual | Señal de validación post-entrada: «esto está completo» |
Pick<T, K> | Mantén solo las propiedades nombradas | Semanalmente | Formas de API pública, modelos de vista |
Omit<T, K> | Elimina las propiedades nombradas | Semanalmente | Eliminación de campos sensibles o irrelevante |
Record<K, V> | Objeto con claves del tipo K y valores del tipo V | Semanalmente | Diccionarios tipados con comprobación de exhaustividad |
ReturnType<F> | Extrae el tipo de retorno de una función | Semanal (especialmente con bibliotecas) | Tipar una variable a partir de un tipo inferido o no exportado |
Parameters<F> | Extrae los tipos de parámetros de una función como una tupla | Ocasional | Funciones envolventes, mocks tipados |
Awaited<T> | Desempaqueta recursivamente tipos de Promise | Ocasional | Obtener el tipo resuelto de funciones asíncronas |
Los que no están en esta lista
TypeScript también incluye Readonly<T>, NonNullable<T>, Extract<T,U>, Exclude<T,U>, InstanceType<C>, ConstructorParameters<C>, y varios tipos literales de plantilla. Son reales y ocasionalmente útiles, pero surgen en código de bibliotecas, utilidades generales y programación de niveles de tipos — no en lógica típica de aplicaciones. Si has memorizado los ocho mencionados anteriormente, busca los demás cuando realmente los necesites.
El principio subyacente es el mismo en todos ellos: describir una transformación de un tipo existente en lugar de duplicarlo. Los nombres específicos de los tipos útiles son solo vocabulario para expresar esa intención al nivel de tipos en TypeScript.
Instalar extensiones
Agregue herramientas IO a su navegador favorito para obtener acceso instantáneo y búsquedas más rápidas
恵 ¡El marcador ha llegado!
Marcador es una forma divertida de llevar un registro de tus juegos, todos los datos se almacenan en tu navegador. ¡Próximamente habrá más funciones!
Herramientas clave
Ver todo Los recién llegados
Ver todoActualizar: Nuestro última herramienta was added on Jun 26, 2026
