6.3 型の絞り込み
ユニオン型の真価は 「型の絞り込み (control flow analysis)」 に対応している点にあります。実行時の値の型を特定する条件分岐を書くことで、ブロック内の型情報がより具体的な型へと自動的に変化します。
6.3.1 等価演算子を用いる絞り込み
Section titled “6.3.1 等価演算子を用いる絞り込み”もっとも基本的な絞り込みは、等価演算子 (===) と if 文などを用いる方法です。
- 条件分岐による型の変化: ユニオン型の変数が特定の値(例:
"none")と一致するかを判定すると、そのブロック内では変数がその型に絞り込まれ、それ以外のブロック(else節など)ではその可能性が除外された型になります。 - 早期リターンとの組み合わせ:
returnを用いて早期に関数から脱出する場合や、条件演算子 (?:) を使った場合でも、TypeScriptコンパイラはコードの流れを理解して適切に型を絞り込みます。
6.3.2 typeof演算子を用いる絞り込み
Section titled “6.3.2 typeof演算子を用いる絞り込み”typeof 演算子は、string | number のようにプリミティブ型が混ざったユニオン型の絞り込みに有効です。
- 判定方法:
if (typeof value === "number")のように記述することで、そのブロック内ではvalueがnumber型として安全に扱え、数値特有のメソッド(toFixedなど)を呼び出せるようになります。 - 注意点:
typeof nullの結果が"object"になるという、JavaScriptの歴史的経緯による例外的な仕様が存在するため注意が必要です。
6.3.3 代数的データ型をユニオン型で再現するテクニック
Section titled “6.3.3 代数的データ型をユニオン型で再現するテクニック”TypeScriptでは、オブジェクト型とユニオン型を組み合わせて、**代数的データ型(タグ付きユニオン)**を擬似的に再現でき、これは非常に強力で頻出する設計パターンです。
- タグの付与:
type Animal = { tag: "animal"; species: string; }のように、各オブジェクト型に自身を判別するための共通プロパティ「タグ」(文字列リテラル型)を持たせます。 - タグによる絞り込み: 合成したユニオン型に対して
if (user.tag === "human")のようにタグを判定することで、TypeScriptはオブジェクトがHuman型であると確信し、Human特有のプロパティへコンパイルエラーなしでアクセスできるようになります。
6.3.4 switch文でも型を絞り込める
Section titled “6.3.4 switch文でも型を絞り込める”タグ付きユニオンのように3つ以上の複数の状態を扱う場合、if 文よりも switch 文を使用する方が有利です。
- 型の網羅性と安全性:
switch (user.tag)で分岐させると、各caseブロックで正しく型が絞り込まれます。 - 修正漏れの防止: 後からユニオン型に新しい種類(例:
Robot型)を追加した際、switch文でそのケースの処理が漏れていると、返り値の型不整合などによりコンパイルエラーが発生しやすくなります。これにより、仕様変更時のバグ(処理の記述漏れ)を未然に防ぐことができます。