【はんべつきょうようたい】

判別共用体 とは?

最終更新:
💡 名札の値で見分ける、複数の型の選択肢

タグで候補を見分けられる共用体。TypeScriptでは、共通プロパティに異なるリテラル値を持つ型をユニオンにし、その値を調べて型を絞り込める。

📌 このページのポイント
共通のタグで、候補とデータを対応させる switch (shape.type) Circle 'circle' 必要なデータ radius Square 'square' 必要なデータ side Triangle 'triangle' 必要なデータ base / height すべてのcaseでreturnした後のdefaultで const check: never = shape; 未処理の候補が残ると、この代入が型エラー
TypeScriptの例。typeのリテラル値で候補を絞り込む。neverによる検査は型検査で行う。
ひよこ ひよこ
普通のユニオン型と何が違うの?
ペンギン先生 ペンギン先生
TypeScriptの例なら、各候補に共通のタグを持たせるんだ。Circleはtype: 'circle'とradius、Squareはtype: 'square'とsideを持つ型として定義し、Circle | Squareにする。タグは単なるstring型ではなく、それぞれのリテラル型にするよ。
ひよこ ひよこ
タグがあると何がうれしいの?
ペンギン先生 ペンギン先生
shape.typeが'circle'かをifで調べると、その枝ではCircleに絞り込めてradiusを使えるんだ。switchでも同じように分岐できる。タグと必要なデータを候補ごとに対応させるのが大事だね。
ひよこ ひよこ
全部の項目を省略可能にするのはだめ?
ペンギン先生 ペンギン先生
typeを'circle' | 'square'にしてradiusやsideを両方省略可能にするだけだと、circleでもradiusがあるとは分からないよ。Circleにはradiusを必須、Squareにはsideを必須とした別々の型を作ると、対応が型に表れるんだ。
ひよこ ひよこ
候補を増やしたときの処理漏れは?
ペンギン先生 ペンギン先生
各caseでreturnするswitchのdefaultで、const check: never = shape;のように代入して検査できるよ。Triangleを追加してそのcaseを書かなければ、残ったTriangleをneverに代入できず型エラーになる。タグを付けるだけで自動的に全分岐が検査されるわけではないんだ。
ひよこ ひよこ
APIの応答にも型を付ければ安全?
ペンギン先生 ペンギン先生
型注釈や型アサーションは、実行時にデータを検査しないよ。外部から届いた値には、タグや必須項目の検証が必要なんだ。検証して候補に合うと確かめた値を扱えば、判別共用体の絞り込みを活かせるね。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「判別共用体」って出てきたら「タグの値で候補を見分けられる共用体」と思えばだいたいOK!
📖 おまけ:英語の意味
「Discriminated Union」 = 判別できる共用体
💬 Discriminated は「区別された」という意味で、タグで区別できるユニオンということだよ

参考資料

← 用語集にもどる