質問の背景:
TypeScriptは、他の厳格に型付けされた言語(例えばJavaやC#)と同様にメソッドのオーバーロードをサポートしていますが、TypeScriptにおけるオーバーロードの構文は概念的に異なります。ここでは、複数のシグネチャが許可されますが、実装は1つだけです。これは、従来のオーバーロードに慣れた開発者にとって混乱を招くことがあります。
問題:
一般的な誤りは、異なるパラメータセットを持つ複数のメソッドを定義しようとすることです。その結果、TypeScriptはすべてのシグネチャの実装を1つ要求するため、コンパイルエラーが発生します。
解決策:
オーバーロードは、メソッドのいくつかのシグネチャを宣言し、その後にすべてのバリエーションに対応する実装を行うことで達成されます。パラメータの正しい識別には、通常、type guardsやinstanceofを使用します。
コードの例:
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}`); } }
主な特徴:
異なるパラメータセットを持つ1つのメソッドの2つの実装を作成できますか?
いいえ。TypeScriptでは、1つの実装のみが許可されています。同じ名前の複数のメソッドは構文エラーです。
メソッドのオーバーロード時にrestパラメータをどのように型付けして厳格な型を失わないようにしますか?
シグネチャでは正確なパラメータを記述し、実装では可能な限り一般的なものを使用することが推奨されます:
class Test { doWork(a: number): void; doWork(a: string): void; doWork(a: number | string): void { //... } }
オーバーロードされたシグネチャの返り値の型が異なる場合、どうなりますか?
TypeScriptは、実装がユニオン型(Union)を返すことを要求します。そうでない場合、コンパイルエラーが発生します。
class X { get(value: number): string; get(value: string): number; get(value: number | string): string | number { return typeof value === 'number' ? 'number' : 42; } }
製品内で異なる型のパラメータに対して同じ名前の2つのメソッドを実装しようとしました。コンパイル後、メソッドは最後の宣言によって「上書き」され、他のすべてのバージョンが無視され、バグが発生しました。
利点:
欠点:
ユニオン型パラメータを持ついくつかのシグネチャを作成し、メソッド内でtype guardsを通じてすべてのバリエーションを処理しました。コンパイラはすぐに型の問題について警告しました。
利点:
欠点: