Comprenez comment les mapped types homomorphes préservent les modificateurs et comment la clause as renomme ou filtre les clés.
Ouvrir cette leçon dans KodokonUn mapped type itère sur un ensemble de clés pour produire un nouveau type objet. La forme [K in keyof T] est dite homomorphe : le compilateur sait que la structure vient de T et recopie automatiquement les modificateurs readonly et ? de chaque propriété d'origine. Les préfixes + et - permettent d'ajouter ou de retirer explicitement ces modificateurs : c'est exactement la mécanique interne de Partial, Required et Readonly.
type Mutable<T> = {
-readonly [K in keyof T]-?: T[K];
};
interface Config {
readonly host?: string;
readonly port?: number;
}
type Draft = Mutable<Config>;
// { host: string; port: number }Depuis TypeScript 4.1, la clause as permet le key remapping : chaque clé peut être renommée à la volée, typiquement via un template literal type. Et si la clause produit never, la clé est purement et simplement supprimée du résultat : c'est le mécanisme officiel de filtrage de propriétés. Notez le & string dans l'exemple : keyof T peut contenir des clés symbol ou number, incompatibles avec un template literal.
type Getters<T> = {
[K in keyof T & string as `get${Capitalize<K>}`]:
() => T[K];
};
interface User { name: string; age: number }
type UserGetters = Getters<User>;
// { getName: () => string; getAge: () => number }
type OnlyMethods<T> = {
[K in keyof T as
T[K] extends (...args: never[]) => unknown
? K : never]: T[K];
};Subtilité de spécification souvent ignorée : appliqué à un tableau ou à un tuple, un mapped type homomorphe ne produit pas un objet avec les clés 0, 1 et length. Le compilateur préserve la nature du type : il transforme les éléments et conserve la forme tableau ou tuple. C'est ce qui permet à Readonly<[number, string]> de rester un tuple. Cette préservation disparaît dès que le mapped type n'est plus homomorphe, par exemple avec [P in K] où K est une union arbitraire de clés.
type Immutable<T> = {
readonly [K in keyof T]: T[K];
};
type Pair = Immutable<[number, string]>;
// readonly [number, string] : le tuple survit
type List = Immutable<string[]>;
// readonly string[]as produit never pour une clé ?{ readonly [K in keyof T]: T[K] } appliqué au tuple [number, string] ?-? dans un mapped type ?