Hintergrund:
TypeScript unterstützt die Überladung von Methoden, ähnlich wie andere stark typisierte Sprachen (z.B. Java oder C#), jedoch unterscheidet sich die Syntax der Überladung in TypeScript konzeptionell. Hier sind mehrere Signaturen erlaubt, aber nur eine Implementierung. Dies kann zu Verwirrung bei Entwicklern führen, die mit der klassischen Überladung vertraut sind.
Problem:
Ein häufiger Fehler ist der Versuch, mehrere Methoden mit unterschiedlichen Parameterlisten zu definieren. Infolgedessen tritt ein Kompilierungsfehler auf, da TypeScript eine Implementierung verlangt, die alle Varianten der Signaturen umsetzt.
Lösung:
Die Überladung wird erreicht, indem mehrere Methodensignaturen deklariert werden, gefolgt von einer Implementierung, die entsprechenden alle Varianten entspricht. Für die korrekte Unterscheidung der Parameter werden typischerweise Type Guards oder instanceof verwendet.
Beispielcode:
class MyLogger { log(message: string): void; log(message: string, level: 'info' | 'error'): void; log(message: string, level?: 'info' | 'error'): void { const lvl = level ?? 'info'; console.log(`[${lvl}] ${message}`); } }
Wesentliche Merkmale:
Kann man zwei Implementierungen einer Methode mit unterschiedlichen Parameterlisten realisieren?
Nein. In TypeScript ist nur eine Implementierung erlaubt. Mehrere Methoden mit demselben Namen sind ein Syntaxfehler.
Wie typisiert man Rest-Parameter bei der Überladung von Methoden, um die strenge Typisierung nicht zu verlieren?
Es wird empfohlen, in den Signaturen genaue Parameter anzugeben und in der Implementierung möglichst allgemein zu sein:
class Test { doWork(a: number): void; doWork(a: string): void; doWork(a: number | string): void { //... } }
Was passiert, wenn der Rückgabewert der überladenen Signaturen unterschiedlich ist?
TypeScript verlangt, dass die Implementierung einen vereinheitlichten Typ (Union) zurückgibt. Andernfalls tritt ein Kompilierungsfehler auf.
class X { get(value: number): string; get(value: string): number; get(value: number | string): string | number { return typeof value === 'number' ? 'number' : 42; } }
Im Produkt wurde versucht, zwei Methoden mit demselben Namen für unterschiedliche Parameterarten in einer Klasse zu implementieren. Nach der Kompilierung "überlagerte" die Methode die letzte Deklaration, alle anderen Versionen wurden ignoriert, was zu Bugs führte.
Vorteile:
Nachteile:
Es wurden mehrere Signaturen mit Union-Type-Parametern erstellt, und die Methode behandelte alle Varianten durch Type Guards. Der Compiler warnte sofort vor Typproblemen.
Vorteile:
Nachteile: