TypeScript 関数オーバーロード

関数オーバーロード(Function Overloading)は、1つの関数に対して複数のシグネチャを定義することを可能にし、コンパイラは渡された引数の型に基づいて正しい実装を選択します。

SVG 図:関数オーバーロードのフロー 背景 タイトル 関数オーバーロードの動作原理 左側 関数オーバーロードのシグネチャ(宣言) // シグネチャ 1 function add(a: number, b: number): number; // シグネチャ 2 function add(a: string, b: string): string; 矢印(下に移動、遮蔽を回避) コンパイラのマッチング(上に移動) コンパイラ マッチング 右側 関数の実装(実際のコード) function add(a: any, b: any): any { return a + b; } すべてのシグネチャと互換性がある必要があります 下半分 呼び出し時の型推論 例 add(1, 2) → number add("a", "b") → string add(true, false) → any 矢印の定義

基本構文

最初に複数の関数シグネチャを宣言し、その後1つの統一された関数を実装します。

例

// 関数オーバーロードのシグネチャ
function add(a: number, b: number): number;
function add(a: string, b: string): string;
function add(a: any, b: any): any {
    return a + b;
}

console.log("数字の加算: " + add(1, 2));
console.log("文字列の加算: " + add("Hello, ", "World"));

実行結果:

数字相加: 3
字符串相加: Hello, World

複数パラメータのオーバーロード

複数のパラメータの異なる組み合わせを定義できます。

例

// 複数のオーバーロードシグネチャ
function greet(name: string): string;
function greet(name: string, greeting: string): string;

// 実装
function greet(name: any, greeting?: any): any {
    if (greeting) {
        return greeting + ", " + name + "!";
    }
    return "Hello, " + name + "!";
}

console.log(greet("Alice"));
console.log(greet("Bob", "Hi"));

実行結果:

Hello, Alice!
Hi, Bob!

メソッドのオーバーロード

クラス内のメソッドでもオーバーロードを使用できます。

例

class Calculator {
    // オーバーロードのシグネチャ
    add(a: number, b: number): number;
    add(a: string, b: string): string;
    add(a: number, b: string): string;
    add(a: any, b: any): any {
        return a + b;
    }
}

var calc = new Calculator();
console.log("数字: " + calc.add(1, 2));
console.log("文字列: " + calc.add("Hello", "World"));
console.log("混合: " + calc.add(5, " apples"));

実行結果:

数字: 3
字符串: HelloWorld
混合: 5 apples

コンストラクタのオーバーロード

コンストラクタも同様にオーバーロードできます。

例

class User {
    name: string;
    age: number;

    // コンストラクタのオーバーロード
    constructor(name: string);
    constructor(name: string, age: number);
    constructor(name: any, age?: any) {
        this.name = name;
        this.age = age || 0;
    }
}

var user1 = new User("Alice");
var user2 = new User("Bob", 25);

console.log("ユーザー1: " + JSON.stringify(user1));
console.log("ユーザー2: " + JSON.stringify(user2));

実行結果:

用户1: {"name":"Alice","age":0}
用户2: {"name":"Bob","age":25}

オーバーロードとユニオン型

ユニオン型ではなくオーバーロードを使用すると、より正確な型推論を得られます。

例

// 推奨:オーバーロードを使用
function process(value: number): number;
function process(value: string): string;
function process(value: any): any {
    if (typeof value === "number") {
        return value * 2;
    }
    return value.toUpperCase();
}

// TypeScript は戻り値の型を認識します
var numResult: number = process(10);  // number
var strResult: string = process("hello");  // string

console.log("数字の結果: " + numResult);
console.log("文字列の結果: " + strResult);

実行結果:

数字结果: 20
字符串结果: HELLO

注意事項

  • オーバーロードのシグネチャは実装のシグネチャの前に置く必要があります
  • 実装のシグネチャはすべてのオーバーロードシグネチャと互換性がある必要があります
  • オーバーロードのシグネチャは型宣言のみであり、実際のコードは生成されません

まとめ

  • 関数オーバーロード:複数のシグネチャを定義し、コンパイラが一致する実装を選択します
  • メソッドのオーバーロード:クラスでも同様に適用可能
  • コンストラクタのオーバーロード:複数の初期化方法を提供します
  • ユニオン型より優れている点:戻り値の型がより正確
その他の拡張