判別可能なユニオン(タグ付きユニオン) は、すべてが共通のリテラルフィールド(判別子)を持つオブジェクト型のユニオンです。コンパイラはこの判別子を使ってバリアントを区別し、安全に絞り込みます。
ts
=
| { : }
| { : ; : }
| { : ; : };
すべてのメンバーが status リテラルを持っています。それをチェックするとちょうど1つのバリアントに絞り込まれ、そのバリアントのフィールドが利用可能になります。
function render(r: Result) {
switch (r.status) {
case "loading": return "...";
case "success": return r.data; // ✅ data exists only here
case "error": return r.message; // ✅ message exists only here
}
}
loading のケースで r.data にアクセスしようとするとコンパイルエラーになります。型システムが不正な組み合わせを 表現不可能 にしてくれるのです。
function render2(r: Result): string {
switch (r.status) {
case "loading": return "...";
case "success": return r.data;
case "error": return r.message;
default:
const _exhaustive: never = r; // ✅ if you add a variant and forget a case, this errors
return _exhaustive;
}
}
never への代入は、すべてのケースを処理することを強制します。新しい status を追加すると、更新が必要なすべての switch をコンパイラが指摘してくれます。
判別可能なユニオンは、状態(loading/success/error)、イベントやアクション(Redux のリデューサー)、そして「いくつかの形のうちの1つ」というデータをモデル化するための定石です。
これらは不正な状態を表現不可能にし、never のテクニックと組み合わせることでコンパイル時の網羅性を保証します。これは緩い boolean やオプショナルフィールドによるモデリングに対する大きな安全性の利点です。
ジュニアからシニアまで、詳細な回答付きのIT面接質問ライブラリ。
寄付する