TypeScript Union型を条件分岐で安全に使い分ける
APIの結果が成功または失敗のどちらかになる場合、両方の項目を任意にした1つの型へ詰め込むと、存在しない値を読みやすくなります。Union型なら、あり得る状態を別々に表せます。
状態ごとに型を定義する
type SaveResult =
| { status: 'success'; id: string }
| { status: 'error'; message: string };statusはどの型かを見分ける目印です。成功時にmessage、失敗時にidはありません。
statusで分岐する
const showResult = (result: SaveResult): string => {
if (result.status === 'success') {
return `保存しました: ${result.id}`;
}
return result.message;
};分岐後はTypeScriptが型を絞り込むため、asによる型アサーションは不要です。
これを「成功か失敗か」を示す1つの型として id?: string と message?: string にすると、成功時でも id がない状態を型が許してしまいます。状態と必要な値を組にできる点がUnion型の利点です。
新しい状態を増やす
読み込み中も表したければ、{ status: 'loading' }をUnionへ追加します。各状態に必要な項目だけを定義でき、不要なundefinedチェックを減らせます。
状態が増えても分岐の書き忘れを検出したい場合は、switchとneverを使えます。
const describe = (result: SaveResult): string => {
switch (result.status) {
case 'success': return `ID: ${result.id}`;
case 'error': return result.message;
default: {
const unhandled: never = result;
return unhandled;
}
}
};SaveResultへ新しい状態を追加すると、defaultの代入が型エラーになり、表示方法の追加を促します。
Union型はコンパイル時の約束です。APIから届く値が本当にその形かは、必要に応じて実行時に検証してください。