TypeScriptは演算子のオーバーロード(operator overloading)を直接サポートしていません—機能やクラスのレベルでこの動作を模倣することしかできません。なぜなら、JavaScript(およびTypeScriptからJSへのトランスパイル)では、ユーザー定義の型に対して標準演算子(+、*、-など)の動作を変更することができないからです。
問題の歴史:C++やC#のような言語では、オブジェクトを操作する際に演算子に対して独自の動作を定義することができます。TypeScript(およびJavaScript)にはそれがなく、出力されるのは通常のJSコードであり、演算子は内部型に厳密に結び付けられています。
問題:抽象エンティティ(例えば、ベクトル、行列、金額など)のあるクラスを開発する際に、演算子を通じて快適に作業することが必要な場合があります。TypeScriptにはこれをネイティブで行うための構文がありません。
解決策:演算子のオーバーロードを模倣するために、視覚的な名前(add、mul、sub)のメソッドを作成したり、時には静的メソッドやユーティリティ関数を使用したりします。また、valueOfメソッドを通じて明示的な型変換を実装することもできますが、これだけではすべての演算子の完全なオーバーロードには不十分であり、この解決策は一部の演算子のプリミティブ値に対してのみ機能します。
コード例:
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 }
主な特徴:
add、sub)が使用されるvalueOfメソッドは一部の演算子に対してのみ機能する、限られた用途valueOf/toStringを定義した場合、クラスの+演算子のオーバーロードは機能しますか?
いいえ。valueOfはプリミティブへの型変換の際の動作にのみ影響します。+演算子(文字列の連結や数値の加算など)に対しては予期しない結果をもたらす可能性があり、他の演算子は調整できません。
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、しかしこれはCurrencyオブジェクトではありません!
TypeScriptでProxyを使用して演算子をオーバーロードできますか?
いいえ。Proxyはプロパティやメソッドへのアクセスをインターセプトしますが、演算子(+、*など)の動作は扱えず、これらは組み込み型に対してのみ機能します。
インターフェースやタイプで宣言を通じて演算子を「オーバーロード」できますか?
いいえ。インターフェースではメソッドや関数のシグネチャしか記述できず、C#のような演算子のオーバーロード(operator+)を記述することはできません。
開発者がCurrencyクラスにvalueOfを追加して数値の表現を取得し、直接数学的操作を行おうとしました(currency1 + currency2)。結果として意味が失われてしまいました;加算の結果は単なる数値であり、通貨オブジェクトではなく、戻り値の型を追跡することができませんでした。
長所:
短所:
Vectorクラスには、新しいVectorを返すaddメソッドが定義されています。明確に型付けされており、あいまいさがありません。
長所:
短所: