Geschichte der Frage
Mit der Entwicklung von TypeScript entstand die Notwendigkeit, den Rückgabewert einer Funktion automatisch zu extrahieren, insbesondere für große Projekte mit vielen miteinander verbundenen Funktionen. Zu diesem Zweck wurde der Utility-Typ ReturnType<T> eingeführt, der seit der Version TypeScript 2.8 in der Standardbibliothek verfügbar ist.
Problem
In großen und komplexen Projekten kann es schwierig sein, die Typen aktuell zu halten — wenn man den Rückgabewert jeder Funktion manuell angibt und zur gleichen Zeit die Signaturen ändert, kann leicht Inkonsistenz entstehen, wenn die Signaturen und Implementierungen nicht übereinstimmen. Darüber hinaus, wenn eine Funktion eine komplexe Struktur zurückgibt, ist es nicht immer einfach, die Beschreibung des Rückgabetyps an allen Verwendungsstellen manuell zu synchronisieren.
Lösung
Der Utility-Typ ReturnType<T> extrahiert automatisch den Rückgabewert von Funktionen und kann zur Typisierung des Ergebnisses eines Funktionsaufrufs an beliebiger Stelle im Code verwendet werden. Dies reduziert die Menge an manueller Pflege der Typinfrastruktur und minimiert Fehler im Zusammenhang mit der Diskrepanz zwischen dem beschriebenen und dem tatsächlichen Rückgabewerttyp.
Beispielcode:
function createUser(name: string, age: number) { return { name, age, created: new Date() }; } type User = ReturnType<typeof createUser>; // User: { name: string; age: number; created: Date; }
Wichtige Eigenschaften:
Kann man ReturnType mit Methoden von Klassen verwenden?
Ja, aber es ist wichtig, den Kontext zu beachten: Wenn die Methode eine Eigenschaft des Objekts mit einer Funktion ist, verwenden Sie ReturnType<obj['methode']>.
Beispielcode:
class MyClass { foo(x: number) { return x * 2; } } type FooReturn = ReturnType<MyClass['foo']>; // Typfehler! // Sollte so sein: type FooReturn = ReturnType<(x: number) => number>; // number // Oder die Methode als Funktion herausziehen: const obj = new MyClass(); type FooReturn2 = ReturnType<typeof obj.foo>;
Was gibt ReturnType für Funktionen mit void/never zurück?
Für eine Funktion mit dem deklarierten Typ void gibt ReturnType void zurück. Für never — never.
Beispielcode:
function doNothing(): void {} type Result = ReturnType<typeof doNothing>; // void
Funktioniert ReturnType mit Funktionsüberladungen?
Nein, ReturnType extrahiert den Rückgabewerttyp der "Implementierung" selbst und nicht von allen Überladungen. Wenn es mehrere Überladungen gibt, wird der beschriebene Implementierungstyp verwendet.
Beispielcode:
function func(x: number): number; function func(x: string): string; function func(x: any): any { return x } type RT = ReturnType<typeof func>; // any
In einem Projekt wird ein manueller Typ für das zurückgegebene Objekt einer Funktion deklariert. Die Funktion ändert sich — der Typ wird nicht aktualisiert, Aufrufe schlagen zur Laufzeit fehl.
Vorteile:
Nachteile:
Wechseln zu ReturnType überall dort, wo der von einer Funktion zurückgegebene Wert verwendet wird. Im Falle von Änderungen ist der Typ immer aktuell.
Vorteile:
Nachteile: