Historia pytania:
TypeScript wspiera przeciążanie metod, podobnie jak inne języki o silnym typowaniu (np. Java lub C#), jednak składnia przeciążania w TypeScript różni się koncepcyjnie. Możliwe jest zdefiniowanie wielu sygnatur, ale tylko jednej implementacji. Może to prowadzić do zamieszania wśród programistów zaznajomionych z klasycznym przeciążaniem.
Problem:
Powszechnym błędem jest próba zdefiniowania kilku metod z różnymi zestawami parametrów. W rezultacie pojawia się błąd kompilacji, ponieważ TypeScript wymaga jednej implementacji, która realizuje wszystkie warianty sygnatur.
Rozwiązanie:
Przeciążanie osiąga się przez deklarację kilku sygnatur metody, a następnie implementację, która odpowiada wszystkim wariantom. Aby poprawnie rozróżnić parametry, zwykle stosuje się type guards lub instanceof.
Przykład kodu:
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}`); } }
Kluczowe cechy:
Czy można zrealizować dwie implementacje jednej metody z różnymi zestawami parametrów?
Nie. W TypeScript dozwolona jest tylko jedna implementacja. Kilka metod o tej samej nazwie to błąd składniowy.
Jak typizować parametry rest przy przeciążaniu metod, aby nie stracić ścisłej typizacji?
Zaleca się w sygnaturach opisywać dokładne parametry, a w implementacji — maksymalnie ogólne:
class Test { doWork(a: number): void; doWork(a: string): void; doWork(a: number | string): void { //... } }
Co się stanie, jeśli zwracany typ przeciążonych sygnatur jest różny?
TypeScript zażąda, aby implementacja zwracała typ złączony (Union). W przeciwnym razie wystąpi błąd kompilacji.
class X { get(value: number): string; get(value: string): number; get(value: number | string): string | number { return typeof value === 'number' ? 'number' : 42; } }
W produkcie próbowano zrealizować dwie metody o tej samej nazwie dla różnych typów parametrów w klasie. Po kompilacji metoda "zastępowała" ostatnie ogłoszenie, wszystkie inne wersje były ignorowane, co prowadziło do błędów.
Zalety:
Wady:
Zrobiono kilka sygnatur z parametrami typu union, a w metodzie obsłużono wszystkie warianty poprzez type guards. Kompilator od razu ostrzegł o problemach typowych.
Zalety:
Wady: