画面の状態が { isLoading: boolean; error?: string; data?: User } で管理されていました。何が問題ですか。
ありえない組み合わせを型として書けてしまうことです。読み込み中なのにデータがある、などを防げません。状態ごとに型を分け、status で区別するユニオンにします。
面接官が見ているのはありえない状態を型で作れてしまう設計に気づき、判別可能なユニオンを提案できるか。
よくある答えと、面談でどう見られるか
- 読み込み中なのにエラーもある、のようなありえない組み合わせを作れてしまう。状態ごとに型を分けたユニオンにする
その通りです。status で分けたユニオンにすれば、ありえない組み合わせは型として書けなくなります。 - 問題は無い。省略可能なプロパティで状態を表すのは普通
よく見る書き方ですが、組み合わせが 2×2×2 通りあり、多くは意味を持ちません。 - error の型を string ではなく Error にすべき
改善にはなりますが、ありえない組み合わせを作れてしまう問題は残ります。 - data を any にすれば柔軟に扱える
検査を捨てるだけです。問題は状態の組み合わせの方です。
模範解答
ありえない組み合わせを型として作れてしまうことが問題です。isLoading が true なのに data がある、error と data が両方ある、といった状態を書けてしまい、画面側はそのすべてに備えるか、無いはずだと信じるしかありません。
状態ごとに型を分けて、ユニオンにします。
type State =
| { status: "loading" }
| { status: "error"; error: string }
| { status: "success"; data: User }これなら「読み込み中なのにエラー」は型として書けません。status で分岐すれば、"success" の中では data が必ずある、と TypeScript が分かります。判別可能なユニオンと呼ばれる書き方です。
出典(一次資料)
対象: TypeScript 5.x〜7.0 照合した一次資料: 公式ドキュメント 照合: 2026-10-25 最終更新: 2026-10-25
お使いの版で挙動が違う場合があります。誤りに気づいたらこの解説を報告するから教えてください。
ここからどう深掘りされるか
この問いに答えられた場合、面談は次の質問に進みます。
観点をすべて押さえられた場合
状態に "empty"(データが0件)を足しました。表示側で書き漏れを防ぐには、どうしておきますか。一部しか触れられなかった場合
判別可能なユニオン(discriminated union)とは、どういう型ですか。