TypeScript nie wspiera bezpośredniego przeciążania operatorów (operator overloading) — możliwe jest tylko naśladowanie tego zachowania na poziomie funkcji/klas, ponieważ JavaScript (i transpilacja TypeScript do JS) nie przewidują możliwości zmiany zachowania standardowych operatorów (+, *, - itp.) dla typów użytkownika.
Historia pytania: w językach takich jak C++ lub C# istnieje możliwość definiowania własnego zachowania dla operatorów podczas pracy z obiektami. W TypeScript (i JavaScript) tego nie ma, ponieważ na wyjściu otrzymujemy zwykły kod JS, w którym operatory są ściśle związane z wewnętrznymi typami.
Problem: przy projektowaniu klas z abstrakcyjnymi bytami (np. wektory, macierze, kwoty pieniężne i tym podobne) czasami konieczne jest zapewnienie wygodnej pracy z nimi za pomocą operatorów. W TypeScript nie ma składni, która pozwoliłaby to zrobić w sposób natywny.
Rozwiązanie: w celu naśladowania przeciążania operatorów tworzy się metody z czytelnymi nazwami (add, mul, sub), czasami używa się metod statycznych lub funkcji pomocniczych. Dodatkowo można zrealizować jawne rzutowanie typów za pomocą metody valueOf, ale to nie wystarcza do pełnego przeciążenia wszystkich operatorów, a to rozwiązanie działa tylko dla niektórych operatorów dla wartości prymitywnych.
Przykład kodu:
class Vector2D { constructor(public x: number, public y: number) {} add(v: Vector2D): Vector2D { return new Vector2D(this.x + v.x, this.y + v.y); } } const v1 = new Vector2D(1, 2); const v2 = new Vector2D(3, 4); const result = v1.add(v2); // Vector2D { x: 4, y: 6 }
Kluczowe cechy:
add, sub)valueOf działa tylko dla niektórych operatorów, w ograniczonym zakresieCzy po zdefiniowaniu valueOf/toString, przeciążenie operatora + dla klas będzie działać?
Nie. valueOf wpływa tylko na zachowanie przy rzutowaniu na typ prymitywny. Dla operatorów + (jak konkatenacja łańcuchów lub dodawanie liczb) może to dać nieoczekiwany wynik, inne operatory nie są konfigurowane.
class Currency { constructor(private amount: number) {} valueOf() { return this.amount; } } const c1 = new Currency(10); const c2 = new Currency(5); console.log(c1 + c2); // 15, ale to nie jest obiekt Currency!
Czy można użyć Proxy do przeciążania operatorów w TypeScript?
Nie. Proxy pozwala przechwytywać dostęp do właściwości i metod, ale nie do operatorów (+, *, itd.), działają one tylko dla typów wbudowanych.
Czy można "przeciążyć" operator przez deklarację w interfejsie lub typie?
Nie. W interfejsach można opisać tylko metody i sygnatury funkcji, nie można opisać przeciżeń operatorów jak np. w C# (operator+)
Programista dodał valueOf do klasy Currency, aby uzyskać reprezentację liczbową i wykonywać operacje matematyczne bezpośrednio (currency1 + currency2). W efekcie utracono semantykę; wynik dodawania to prosta liczba, a nie obiekt walutowy, niemożliwe było śledzenie typu zwracanego wartości.
Zalety:
Wady:
W klasie Vector zaimplementowano metodę add, która zwraca nowy wektor. Wyraźnie typizowane, bez wątpliwości.
Zalety:
Wady: