TypeScriptのUnion型の引数を用いた関数で、変数の型の絞り込み

Union型の引数を用いて変数の型を絞り込み

TypeScriptにおいて、Union型の引数を用いて変数の型を絞り込む例を示します。

例えば、次のようなUnion型の引数を持つ関数を考えてみます。

type Pet = {
    name: string;
};

type Cat = Pet & {
    meow: () => void;
};

type Dog = Pet & {
    bark: () => void;
};

// Union型の引数を受け取る関数
function feedPet(pet: Cat | Dog) {
    // petがCat型の場合
    if ('meow' in pet) {
        pet.meow(); // 安全にmeowメソッドを呼び出せる
    }
    // petがDog型の場合
    else if ('bark' in pet) {
        pet.bark(); // 安全にbarkメソッドを呼び出せる
    }
    // その他の場合はエラー
    else {
        throw new Error('Unexpected pet type');
    }
}

// 使用例
let myPet: Cat = {
    name: 'Fluffy',
    meow: () => console.log('Meow!')
};

feedPet(myPet); // feedPet関数にCat型のオブジェクトを渡すことができる

この例では、feedPet関数がCat型またはDog型の引数を受け取るUnion型を持ちます。
関数内部ではif ('meow' in pet)のように、in演算子を使用して特定のプロパティが存在するかどうかをチェックし、それに基づいて型の絞り込みを行っています。
これにより、実行時に安全にメソッドを呼び出すことができます。

タグ付きUnion型で絞り込みをする例

タグ付きUnion型を使用して変数の型を絞り込む例を示します。
タグ付きUnion型は、Union型の各メンバーに明示的な識別子(タグ)を付ける方法です。

// タグ付きUnion型の定義
type Pet = {
    type: 'cat';
    name: string;
    meow: () => void;
} | {
    type: 'dog';
    name: string;
    bark: () => void;
};

// 関数
function feedPet(pet: Pet) {
    // タグを使って型の絞り込みを行う
    switch (pet.type) {
        case 'cat':
            pet.meow(); // 安全にmeowメソッドを呼び出せる
            break;
        case 'dog':
            pet.bark(); // 安全にbarkメソッドを呼び出せる
            break;
        default:
            throw new Error('Unexpected pet type');
    }
}

// 使用例
let myCat: Pet = {
    type: 'cat',
    name: 'Fluffy',
    meow: () => console.log('Meow!')
};

let myDog: Pet = {
    type: 'dog',
    name: 'Buddy',
    bark: () => console.log('Woof!')
};

feedPet(myCat); // feedPet関数にCat型のオブジェクトを渡すことができる
feedPet(myDog); // feedPet関数にDog型のオブジェクトを渡すことができる

この例では、Pet型はtypeプロパティを持つUnion型として定義されています。
関数feedPet内ではswitch文を使ってpet.typeの値に基づいて型の絞り込みを行い、安全に各種メソッドを呼び出しています。
これにより、実行時の型エラーを回避しながら、型安全性を保つことができます。