TypeScript Type Guardでユニオン型を安全に絞り込む - isキーワード活用法
問題
APIレスポンスが成功・失敗の2つの型のユニオンで返ってくる場合、if文の中で型が絞り込まれず、毎回型アサーションを書かなければならない状況が発生します。
type SuccessResponse = { status: 'ok'; data: string[] };
type ErrorResponse = { status: 'error'; message: string };
type ApiResponse = SuccessResponse | ErrorResponse;
function handle(res: ApiResponse) {
// res.dataにアクセスできない - 型が絞り込まれていない
}
解決方法
isキーワードを使ったカスタムType Guard関数を作成します。
function isSuccess(res: ApiResponse): res is SuccessResponse {
return res.status === 'ok';
}
function handle(res: ApiResponse) {
if (isSuccess(res)) {
// ここではresがSuccessResponseに絞り込まれます
console.log(res.data);
} else {
// ここではresがErrorResponseになります
console.log(res.message);
}
}
配列のフィルタリングでも便利です。
const results: (string | null)[] = ['a', null, 'b', null];
// filterの後も(string | null)[]型のまま...
const bad = results.filter(x => x !== null);
// Type Guardでstring[]に絞り込み
const good = results.filter((x): x is string => x !== null);
ポイント
isキーワードは戻り値の型の位置に書き、関数がtrueを返すとその型に絞り込まれますArray.filterにType Guardを渡すと、結果の配列の型が自動的に絞り込まれますtypeofやin演算子では対応できない複雑な型分岐で特に役立ちます