Inicio > Cursos > TypeScript > Mapped Types y Conditional Types
TypeScriptTipos AvanzadosLección 9 de 18

Mapped Types y Conditional Types

Los Mapped Types son como un map() de JavaScript pero para los tipos de TypeScript: aplican una transformación a cada propiedad de un tipo y crean uno nuevo. La sintaxis [K in keyof T] itera sobre cada clave K del tipo T, y defines qué hacer con ella. Es cómo están implementados Partial, Readonly y Required internamente en TypeScript.

Puedes incluso renombrar claves mientras mapeas, creando por ejemplo Getters<T> que convierte cada propiedad en un método getter.

Los Conditional Types aplican lógica: "si T extiende U, el tipo es X; de lo contrario, es Y". Es como un operador ternario (?:) pero para tipos. La palabra clave infer dentro de un conditional type permite extraer un subtipo: si T extends Promise<infer R>, TypeScript extrae el tipo R que está dentro de la Promise.

Con esto puedes construir tipos como PromiseResult<T> que, si T es una Promise, devuelve el tipo que resuelve, o T directamente si no lo es.

// Mapped Type — transforma cada propiedad
type Opcional<T> = { [K in keyof T]?: T[K] };       // = Partial<T>
type Inmutable<T> = { readonly [K in keyof T]: T[K] }; // = Readonly<T>

// Mapped type con transformación de clave
type Getters<T> = {
  [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
// Getters<{ nombre: string }> = { getNombre: () => string }

type Setters<T> = {
  [K in keyof T as `set${Capitalize<string & K>}`]: (val: T[K]) => void;
};

// Conditional Types
type EsString<T> = T extends string ? true : false;
type R1 = EsString<string>;  // true
type R2 = EsString<number>;  // false

// Distributive conditional type
type Nullable<T> = T extends any ? T | null : never;
// Nullable<string | number> = string | null | number | null

// infer — extraer tipos dentro de conditional types
type ElementoDeArray<T> = T extends Array<infer Item> ? Item : never;
type Num = ElementoDeArray<number[]>; // number
type Str = ElementoDeArray<string[]>; // string

type PromiseResult<T> = T extends Promise<infer R> ? R : T;
type AsyncStr = PromiseResult<Promise<string>>; // string
type SyncNum = PromiseResult<number>;           // number

// DeepPartial — recursivo
type DeepPartial<T> = {
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
Consejo🧬 infer dentro de conditional types es la herramienta más poderosa de TypeScript avanzado. Permite extraer tipos de estructuras complejas como Promise<T>, Array<T> o funciones.
← Utility TypesTemplate Literal Types y satisfies →

Practica esta lección

Resuelve los ejercicios del curso de TypeScript en la app, gratis y con corrección automática.

Empezar a practicar