Les mapped types transforment chaque propriété d'un type existant.
// Rendre toutes les props optionnelles (comme Partial) type MyPartial<T> = { [K in keyof T]?: T[K]; }; // Rendre toutes les props readonly type Freeze<T> = { readonly [K in keyof T]: T[K]; }; // Rendre nullable toutes les props type Nullable<T> = { [K in keyof T]: T[K] | null; }; // Remapper les clés avec 'as' type Getters<T> = { [K in keyof T as `get${Capitalize}` ]: () => T[K]; };
// Syntaxe : T extends U ? X : Y type IsString<T> = T extends string ? "yes" : "no"; type A = IsString<string>; // "yes" type B = IsString<number>; // "no" // NonNullable custom type MyNonNullable<T> = T extends null | undefined ? never : T; // Extraire le type des éléments d'un tableau type ElementType<T> = T extends (infer E)[] ? E : never; type Nums = ElementType<number[]>; // number // infer — extraire un type dans une position type UnpackPromise<T> = T extends Promise<infer U> ? U : T; type Value = UnpackPromise<Promise<string>>; // string
// keyof — union de toutes les clés d'un type interface User { id: number; name: string; email: string; } type UserKey = keyof User; // "id" | "name" | "email" // typeof — type d'une valeur runtime const config = { host: "localhost", port: 3000 }; type Config = typeof config; // { host: string; port: number } // Combiné — accès sécurisé à une propriété function pluck<T, K extends keyof T>(obj: T, keys: K[]): T[K][] { return keys.map(k => obj[k]); } pluck(config, ["host", "port"]); // (string | number)[]
// Combiner des types littéraux comme des template strings type Orientation = "horizontal" | "vertical"; type Alignment = "start" | "center" | "end"; type FlexClass = `flex-${Orientation}-${Alignment}`; // "flex-horizontal-start" | "flex-horizontal-center" | ... (6 combos) // Générer des event handlers type EventName = "click" | "focus" | "blur"; type EventHandler = `on${Capitalize}` ; // "onClick" | "onFocus" | "onBlur" // Route typée type ApiRoute = `/api/${string}`; const route: ApiRoute = "/api/users"; // OK
// typeof guard function process(val: string | number) { if (typeof val === "string") { val.toUpperCase(); // TS sait que val est string ici } else { val.toFixed(2); // TS sait que val est number ici } } // instanceof guard function handleError(e: unknown) { if (e instanceof Error) console.log(e.message); } // Custom type guard — prédicat de type function isUser(val: unknown): val is User { return typeof val === "object" && val !== null && "id" in val && "name" in val; } // Assertion function function assertString(val: unknown): asserts val is string { if (typeof val !== "string") throw new TypeError("Expected string"); }
type A = string | number | boolean; // Exclude<T, U> — retire U de T type B = Exclude<A, boolean>; // string | number // Extract<T, U> — garde uniquement U dans T type C = Extract<A, string | number>; // string | number // NonNullable — retire null et undefined type D = NonNullable<string | null | undefined>; // string // Awaited — déplie les Promises imbriquées type E = Awaited<Promise<Promise<string>>>; // string