TypeScriptでは、異なる型や引数の数を持つ複数の関数シグネチャを宣言することで関数のオーバーロードを実現しますが、実装は1つだけです。
主な特徴:実装は常に1つだけで、コンパイラーは呼び出しが宣言されたシグネチャの1つに一致するかどうかをチェックします。
function greet(person: string): string; function greet(person: string, age: number): string; function greet(person: string, age?: number): string { if (age !== undefined) { return `Hello, ${person}. You are ${age}!`; } else { return `Hello, ${person}!`; } } greet('Alice'); // 'Hello, Alice!' greet('Bob', 32); // 'Hello, Bob. You are 32!'
⚠️ C#やJavaとは異なり、関数の複数の実装はありません — すべてのシグネチャは1つの関数に解決され、内部での必須チェックがあります。
TypeScriptでオーバーロードされた各シグネチャをC#のように別々の関数として実装する必要がありますか?
答え: いいえ!TypeScriptでは、オーバーロードされた関数には1つの実装しか存在しません。すべてのバリエーションはシグネチャの宣言のセットを通じて指定されます。実装は、1つの関数内で異なる入力パラメータのさまざまなケースを自己管理する必要があります。
物語
プロジェクトで開発者はJavaのようにオーバーロードを期待して同じ名前の関数を2つ宣言しました。その結果、最後に定義された関数のみが動作し、その他は「上書き」されてしまいました。これにより、意図しないエラーが発生し、リファクタリングに膨大な時間がかかりました。
物語
オーバーロードされた関数の実装内で型の適切なチェックが行われませんでした。関数は顧客が期待していた型とは異なる値を時折返すことがあり、そのためTypeScriptがオーバーロードの実装を検証しないためにエラーを捕まえるのが難しくなりました。
物語
型レベルでのオーバーロードの実装のみを使用し(シグネチャを宣言)、ランタイム実装との互換性を確保しませんでした(オプショナルパラメータの欠如や関数内の処理)。これにより、「型的には有効」とされるパラメータによる呼び出し時にクラッシュが発生しました。なぜなら、それらのケースをランタイムがサポートしていなかったからです。