Verstehe, wie homomorphe Mapped Types Modifikatoren bewahren und wie die as-Klausel Schlüssel umbenennt oder filtert.
Diese Lektion in Kodokon öffnenEin Mapped Type iteriert über eine Menge von Schlüsseln, um einen neuen Objekttyp zu erzeugen. Die Form [K in keyof T] heißt homomorph: Der Compiler weiß, dass die Struktur von T stammt, und kopiert automatisch die Modifikatoren readonly und ? jeder ursprünglichen Eigenschaft. Mit den Präfixen + und - fügst du diese Modifikatoren ausdrücklich hinzu oder entfernst sie: Genau das ist die interne Mechanik hinter Partial, Required und 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 }Seit TypeScript 4.1 ermöglicht die as-Klausel das Key Remapping: Jeder Schlüssel kann im Vorbeigehen umbenannt werden, typischerweise über einen Template-Literal-Typ. Und wenn die Klausel never erzeugt, wird der Schlüssel schlicht aus dem Ergebnis entfernt: Das ist der offizielle Mechanismus, um Eigenschaften zu filtern. Beachte das & string im Beispiel: keyof T kann Schlüssel vom Typ symbol oder number enthalten, die mit einem Template-Literal nicht vereinbar sind.
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];
};Eine oft übersehene Feinheit der Spezifikation: Auf ein Array oder ein Tupel angewendet, erzeugt ein homomorpher Mapped Type kein Objekt mit den Schlüsseln 0, 1 und length. Der Compiler bewahrt die Natur des Typs: Er transformiert die Elemente und behält die Array- oder Tupelform bei. Genau deshalb bleibt Readonly<[number, string]> ein Tupel. Diese Bewahrung verschwindet, sobald der Mapped Type nicht mehr homomorph ist, zum Beispiel bei [P in K], wobei K eine beliebige Union von Schlüsseln ist.
type Immutable<T> = {
readonly [K in keyof T]: T[K];
};
type Pair = Immutable<[number, string]>;
// readonly [number, string]: the tuple survives
type List = Immutable<string[]>;
// readonly string[]as-Klausel für einen Schlüssel never erzeugt?{ readonly [K in keyof T]: T[K] }, angewendet auf das Tupel [number, string]?-? in einem Mapped Type?