ProgrammingTypeScriptアーキテクト

TypeScriptで演算子のオーバーロード(operator overloading)を実装するにはどうすればよいですか?これは直接可能ですか?回避策はどのようなものですか?

Hintsage AIアシスタントで面接を突破

回答。

TypeScriptは演算子のオーバーロード(operator overloading)を直接サポートしていません—機能やクラスのレベルでこの動作を模倣することしかできません。なぜなら、JavaScript(およびTypeScriptからJSへのトランスパイル)では、ユーザー定義の型に対して標準演算子(+*-など)の動作を変更することができないからです。

問題の歴史:C++やC#のような言語では、オブジェクトを操作する際に演算子に対して独自の動作を定義することができます。TypeScript(およびJavaScript)にはそれがなく、出力されるのは通常のJSコードであり、演算子は内部型に厳密に結び付けられています。

問題:抽象エンティティ(例えば、ベクトル、行列、金額など)のあるクラスを開発する際に、演算子を通じて快適に作業することが必要な場合があります。TypeScriptにはこれをネイティブで行うための構文がありません。

解決策:演算子のオーバーロードを模倣するために、視覚的な名前(addmulsub)のメソッドを作成したり、時には静的メソッドやユーティリティ関数を使用したりします。また、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 }

主な特徴:

  • 組み込みのオーバーロードサポートはない
  • 明示的なメソッド(addsub)が使用される
  • 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+)を記述することはできません。

一般的なエラーとアンチパターン

  • operator+(a, b)のような関数を書くことを試み、その動作を期待する
  • ビジネスロジックを実装するためにvalueOfを使用する(valueOfのテンプレートメソッドはコードを不明瞭にする)
  • 単純な値の置き換えとクラスのロジックを同じクラスに結合する

実生活の例

ネガティブなケース

開発者がCurrencyクラスにvalueOfを追加して数値の表現を取得し、直接数学的操作を行おうとしました(currency1 + currency2)。結果として意味が失われてしまいました;加算の結果は単なる数値であり、通貨オブジェクトではなく、戻り値の型を追跡することができませんでした。

長所:

  • 短い表現(currency1 + currency2)
  • 基本的な操作においてコードが少ない

短所:

  • 型安全性の喪失
  • 返されるオブジェクトの制御不可
  • デバッグが複雑になる

ポジティブなケース

Vectorクラスには、新しいVectorを返すaddメソッドが定義されています。明確に型付けされており、あいまいさがありません。

長所:

  • 厳格な型付け
  • 操作の安全性
  • メンテナンスの利便性

短所:

  • v1 + v2と書くことはできず、v1.add(v2)のみ
  • 演算子オーバーロードのある言語に比べてやや冗長な記述