TypeScript-infer-Schlüsselwort
infer ist ein Schlüsselwort in bedingten Typen von TypeScript, mit dem neue Typen aus vorhandenen Typen abgeleitet werden.
Es ermöglicht das Extrahieren und Ableiten von Typen innerhalb generischer bedingter Typen und erlaubt leistungsstarke Typoperationen.
SVG-Diagramm: Wie infer funktioniert
Warum wird das infer-Schlüsselwort benötigt?
In der generischen Programmierung müssen wir oft Teiltypen aus komplexen Typen extrahieren.
Zum Beispiel ausPromise<string>extractstring, fromArray<User>extractUser。
Das infer-Schlüsselwort macht eine solche Typenextraktion elegant und typsicher. Es ermöglicht, eine Typvariable in einem bedingten Typ zu deklarieren und sie dann im wahren Zweig zu verwenden.
Konzepterklärung:infer ist die Abkürzung von "infer", was "ableiten" bedeutet. Es kann nur in der extends-Klausel eines bedingten Typs verwendet werden, um eine Typvariable zu deklarieren, die abgeleitet werden soll.
Grundlegende Verwendung
Verwende infer, um Typen in bedingten Typen abzuleiten.
Beispiel
// Wenn T Promise<V> ist, V zurückgeben; andernfalls never zurückgeben
type ValueOf<T> = T extends Promise<infer V> ? V : never;
// Test
type Str = ValueOf<Promise<string>>; // string
type Num = ValueOf<Promise<number>>; // number
type NotPrm = ValueOf<string>; // never
// Anwendungsbeispiel
var promise: Promise<string> = Promise.resolve("hello");
var value: ValueOf<typeof promise> = "Welt";
console.log("Zeichenkettenextraktion: " + (typeof value === "string" ? "Erfolg" : "Fehler"));
Ausgabe:
String extraction: success
Erklärung:
infer VEine Typvariable V wird deklariert, und TypeScript leitet den Typ von V automatisch ab.
Array-Elementtypen extrahieren
Den Elementtyp aus einem Array-Typ extrahieren.
Beispiel
// Wenn T ein Array V[] ist, V zurückgeben
type ArrayElement<T> = T extends (infer V)[] ? V : never;
// Test
type User = { name: string };
type Users = User[];
type E1 = ArrayElement<string[]>; // string
type E2 = ArrayElement<Users>; // User
type E3 = ArrayElement<number>; // never (kein Array)
// Anwendungsbeispiel
var users: Users = [{ name: "Alice" }];
var element: ArrayElement<Users> = users[0];
console.log("Elementtyp: " + element.name);
Anwendungsfälle:Dieses Muster wird häufig verwendet, um Elemente eines bestimmten Typs aus Union-Typen zu extrahieren.
Rückgabetypen von Funktionen extrahieren
Extrahiere den Rückgabetyp aus einem Funktionstyp.
Beispiel
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
// Test
function getData() {
return { id: 1, name: "Alice" };
}
function fetchUser(id: number): Promise<User> {
return Promise.resolve({ id, name: "Bob" });
}
type R1 = ReturnType<typeof getData>; // { id: number; name: string }
type R2 = ReturnType<typeof fetchUser>; // Promise<User>
// Anwendungsbeispiel
var result: R1 = { id: 1, name: "Test" };
console.log("Rückgabetyp: " + JSON.stringify(result));
Eingebaute Typen:TypeScripts eingebaute
ReturnType<T>Utility-Typen werden mit infer implementiert.
Extrahieren von Funktionsparametertypen
Parametertypen aus einem Funktionstyp extrahieren.
type FirstParameter<T> = T extends (first: infer P, ...rest: any[]) => any ? P : never;
// Test
function createUser(name: string, age: number): Benutzer {
return { id: 1, name };
}
function logMessage(msg: string): void {
console.log(msg);
}
type P1 = FirstParameter<typeof createUser>; // string
type P2 = FirstParameter<typeof logMessage>; // string
type P3 = FirstParameter<() => void>; // never
// Anwendungsbeispiel
var nameParam: P1 = "Alice";
console.log("Parametertyp: " + nameParam);
Hinweis:Sie können verwenden
...rest: any[]um beliebig viele verbleibende Parameter abzugleichen.
Mehrfaches infer
Verwendung von mehrfachem infer in einem bedingten Typ.
Beispiel
type FirstTwo<T> = T extends [infer A, infer B, ...rest: any[]] ? [A, B] : never;
// Test
type Tuple = [string, number, boolean];
type FirstTwoTypes = FirstTwo<Tuple>; // [string, number]
// Objekteigenschaften extrahieren
type ObjectValue<T> = T extends { value: infer V } ? V : never;
type WithValue = { value: string; name: string };
type ExtractedValue = ObjectValue<WithValue>; // string
// Anwendungsbeispiel
var tupleResult: FirstTwoTypes = ["hello", 123];
console.log("Tupel: " + JSON.stringify(tupleResult));
Tupel:Verwenden
...rest: any[]um die restlichen Elemente eines Tupels abzugleichen.
Verwendung von infer in rekursiven Typen
Verwenden Sie infer in rekursiven Typ-Dienstprogrammen, um komplexe Typoperationen zu implementieren.
Beispiel
type DeepReadonly<T> = T extends Function
? T
: T extends object
? { readonly [P in keyof T]: DeepReadonly<T[P]> }
: T;
// Test
interface User {
name: string;
address: {
city: string;
zip: string;
};
}
type ReadonlyUser = DeepReadonly<User>;
// Promise-Typen abflachen
type FlattenPromise<T> = T extends Promise<infer U>
? U extends Promise<any>
? FlattenPromise<U>
: U
: T;
type Nested = Promise<Promise<string>>;
type Flat = FlattenPromise<Nested>; // string
// Anwendungsbeispiel
var user: ReadonlyUser = {
name: "Alice",
Adresse: { Stadt: "Peking", Postleitzahl: "100000" }
};
// user.name = "Bob"; // Fehler: readonly
console.log("Tiefes readonly: " + user.name);
Rekursives infer:Die Verwendung von infer in rekursiven Typen ermöglicht tiefe Typumwandlungen, wie tiefes readonly, tiefes partial usw.
Hinweise
- Kann nur auf der rechten Seite von extends verwendet werden:infer kann nur in der extends-Klausel eines bedingten Typs verwendet werden
- Deklarieren von Typvariablen:Verwenden Sie
infer Vum die Typvariable zu deklarieren, die inferiert werden soll. - Mehrfache Verwendung erlaubt:Mehrere infer können in einem einzelnen bedingten Typ verwendet werden
- Gibt never zurück, wenn die Inferenz fehlschlägt:Wenn die Inferenz fehlschlägt, gibt der bedingte Typ never zurück
Best Practices:infer ist der Kern der Implementierung benutzerdefinierter Utility-Typen; seine Beherrschung ermöglicht mächtige Typoperationen.
Zusammenfassung
infer ist eine der mächtigsten Funktionen im TypeScript-Typsystem.
- Typ-Extraktion:Teiltypen aus komplexen Typen extrahieren
- Bedingte Inferenz:Typen innerhalb bedingter Typen ableiten
- Funktionsbezogen:Extrahieren von Funktionsparametern und Rückgabetypen
- Rekursive Hilfstypen:Implementierung tiefer Typentransformationen
Andere ErweiterungenEmpfehlung:Ein tiefes Verständnis von infer ermöglicht es Ihnen, fortgeschrittenere Typ-Hilfsmittel zu schreiben, was die Typsicherheit und die Entwicklungseffizienz verbessert.