Skip to content

Génériques TypeScript expliqués

Les motifs de génériques auxquels vous avez recours, regroupés par rôle : déclarer un paramètre de type, le contraindre, lui donner une valeur par défaut, brancher avec un type conditionnel, capturer avec infer et transformer une forme. Chaque ligne associe le motif à un exemple en une ligne.

Un générique est un paramètre de type : un espace réservé pour un type que l’appelant choisit, si bien qu’une même fonction ou un même type convient à plein de formes sans perdre en précision. Lisez <T> comme « pour un certain type T ». La puissance vient de la contrainte de T, du branchement sur T et de la transformation de T. Les motifs ci-dessous forment le vocabulaire de travail.

Tableau de référence · 28 entrées
28 of 28 rows
Déclarer
Un paramètre de type choisi par l’appelant.function first<T>(xs: T[]): T
Plusieurs paramètres de type indépendants.function pair<T, U>(a: T, b: U): [T, U]
Un second paramètre lié aux clés du premier.function get<T, K extends keyof T>(o: T, k: K): T[K]
Une classe avec un paramètre de type sur ses champs et ses méthodes.class Box<T> { value: T }
Une forme d’objet avec un paramètre de type.interface Result<T> { data: T }
Un paramètre de type sur une fonction fléchée ; la virgule finale empêche les fichiers .tsx de l’interpréter comme du JSX.const first = <T,>(xs: T[]): T => xs[0]
Contraindre
Exige que T soit assignable à Type.function len<T extends { length: number }>(x: T)
Restreint T à une clé d’un autre type.type Keys<O> = keyof O
Restreint T à une classe constructible.function make<C extends new () => C>(c: C): C
Exige que T satisfasse plusieurs contraintes à la fois.function log<T extends Error & { code: number }>(e: T)
Restreint à n’importe quoi ; garde le paramètre générique sans le rétrécir.type Wrap<T> = T extends unknown ? { v: T } : never
Par défaut et inférence
Donne à T une valeur par défaut quand l’appelant l’omet.function parse<T = string>(): T
Capture un type à l’intérieur d’un conditionnel.type El<T> = T extends Array<infer I> ? I : never
Déballe un Promise imbriqué jusqu’à son type interne.type Data = Awaited<Promise<User>>
Capture un morceau d’un type littéral de gabarit.type Path<S> = S extends `/api/${infer R}` ? R : never
Vérifie toute l’union d’un coup ; un T nu infère un membre à la fois.type El<T> = [T] extends [Array<infer I>] ? I : never
Conditionnels et mappés
Choisit un type selon que T est assignable à U.type IsStr<T> = T extends string ? true : false
Construit un nouveau type d’objet en transformant chaque clé de T.type Frozen<T> = { [K in keyof T]: Readonly<T[K]> }
Un objet dont les clés sont K et les valeurs V.type Scores = Record<string, number>
Génériques intégrés dérivés des motifs ci-dessus.type Preview = Pick<User, "id" | "name">
Un T nu avant extends s’exécute une fois par membre de l’union et unit les résultats.ToArray<'a' | 'b'> = 'a'[] | 'b'[]
Ajoute ou retire des modificateurs sur les clés mappées.type Req<T> = { [K in keyof T]-?: T[K] }
Les clés d’une valeur d’exécution, sous forme de type.const opts = { a: 1 }; type K = keyof typeof opts
Construit un type de chaîne à partir d’autres types de chaîne.type Route = `/users/${string}`
Concatène des types tuples bout à bout.type Concat<T extends unknown[], U extends unknown[]> = [...T, ...U]
Un type dont la définition se référence lui-même.type Json = string | number | Json[] | { [k: string]: Json }
Vérifie une valeur contre un type et conserve son type littéral plus étroit.const c = { dark: "#000" } satisfies Record<string, string>
Conserve le type littéral de l’appelant au lieu de l’élargir (TS 5.0).function first<const T>(xs: readonly T[]): T