Day 3・ユニオン・絞り込み・ジェネリクス(読める範囲で)
型の絞り込み(narrowing)
ユニオン型を安全に扱うため、条件分岐で型を1つに絞り込む方法を学ぶ。
ユニオン型はそのままだと使いにくい
string | number という値があるとき、いきなり文字列専用のメソッドを呼ぶことはできません。文字列かもしれないし数値かもしれないからです。そこで if などで条件を確認し、その分岐の中では「今は文字列だ」と型を1つに狭めます。これを型の絞り込み(narrowing)と呼びます。
function format(value: string | number): string {
if (typeof value === "string") {
// このブロックの中では value は string 扱い
return value.toUpperCase();
}
// ここまで来たら value は number 扱い
return value.toFixed(2);
}なぜ絞り込みが必要か
TypeScriptは「まだ文字列か数値か分からない値」に対して、文字列専用の操作を許しません。もし許すと、数値のときに toUpperCase() を呼んで実行時エラーになるからです。絞り込みは「今この分岐では安全に使える」ことを型で証明する仕組みです。
絞り込みの手段はいくつかあります。値の種類を調べる typeof、リテラル型を直接比較する ===、値が存在するかを確認する if などです。特にリテラルのユニオンでは === が主役になります。
type Status = "idle" | "loading" | "done";
function label(status: Status): string {
if (status === "loading") {
return "読み込み中...";
}
if (status === "done") {
return "完了しました";
}
return "待機中"; // ここでは status は "idle" に絞られている
}絞り込まずに使う
文字列か数値か分からないまま操作しようとする
function f(v: string | number) {
return v.toUpperCase(); // エラー: number には無い
}絞り込んでから使う
typeof で確認した分岐の中でだけ操作する
function f(v: string | number) {
if (typeof v === "string") return v.toUpperCase();
return String(v);
}「値があるか」の確認も絞り込み
string | undefined のような型では、いきなり使うとエラーになります。if (value) { ... } のように存在を確認すると、その中では undefined が除かれた型に絞り込まれます。AIが生成したコードで赤線が出たら、多くはこの確認が抜けているのが原因です。
AIにはこう聞く
「この関数の引数は string | number。分岐で型を絞り込んで、それぞれ適切に処理して」と頼むと、typeof を使った安全な分岐を書いてくれます。赤線が残ったら「絞り込みが足りない箇所を教えて」と続けて聞きましょう。
読んでも腑に落ちない所は、AIに噛み砕いてもらいましょう。
理解度チェック
答えられれば、面接で説明できる状態に一歩近づきます。
value: string | number に対して value.toFixed(2) を安全に呼ぶには、どの絞り込みが必要?
型の絞り込み(narrowing)を最もよく表しているのはどれ?
string | undefined 型の値をそのまま使うと赤線が出ます。なぜ出るのか、どう対処するのかを説明してください。
記述式です。まず自分の言葉で答えを考えてから、模範解答を開いて自己採点してください。