判別プロパティによる型の絞り込み
TypeScriptにswitch文内のバリエーションを絞り込ませます。
「判別プロパティによる型の絞り込み」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。
判別子による絞り込み
判別子をチェックすると、TypeScriptはユニオンを一致するメンバーに絞り込み、そのメンバー固有のフィールドを使えるようにします。これがこのパターンの利点です。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape) {
if (s.kind === "circle") return Math.PI * s.radius ** 2;
return s.side ** 2;
}
console.log(area({ kind: "circle", radius: 2 }).toFixed(2));判別子をswitchで処理する
判別子に対するswitchは、すべてのバリアントを処理する最も明確な方法です。各caseの中では、型が自動的に絞り込まれます。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
}
}
console.log(area({ kind: "square", side: 5 }));各caseで使えるメンバー固有のフィールド
"circle"のcaseではs.radiusを使えますが、s.sideは使えません。TypeScriptは現在どのメンバーを扱っているかを正確に把握しています。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function describe(s: Shape) {
switch (s.kind) {
case "circle": return "r=" + s.radius;
case "square": return "side=" + s.side;
}
}
console.log(describe({ kind: "circle", radius: 9 }));ifによる絞り込み
switchを使う必要はありません。判別子を単純なifで比較しても、同じように効果的に絞り込めます。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function perimeter(s: Shape): number {
if (s.kind === "circle") {
return 2 * Math.PI * s.radius;
}
return 4 * s.side;
}
console.log(perimeter({ kind: "square", side: 3 }));誤ったフィールドへのアクセスは失敗する
絞り込みを行う前は、メンバー固有のフィールドにアクセスできません。そのプロパティがすべてのメンバーに存在するわけではないため、TypeScriptがエラーを報告します。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function broken(s: Shape) {
// Error: radius does not exist on Square
// return s.radius;
return s.kind;
}
console.log(broken({ kind: "square", side: 1 }));boolean判別子による絞り込み
{ ok: true } | { ok: false }というユニオンでは、if (r.ok)をチェックすると成功メンバーに絞り込まれます。
type Result =
| { ok: true; data: string }
| { ok: false; error: string };
function handle(r: Result): string {
if (r.ok) return "Data: " + r.data;
return "Error: " + r.error;
}
console.log(handle({ ok: false, error: "boom" }));早期returnによる絞り込み
一方のバリアントで早期returnすると、残りのコードでは他のバリアントに絞り込まれます。ケースを1つずつ処理していく、すっきりした方法です。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function label(s: Shape): string {
if (s.kind === "circle") return "circle";
// s is now narrowed to Square here
return "square with side " + s.side;
}
console.log(label({ kind: "square", side: 8 }));他の条件との組み合わせ
判別子のチェックを他のロジックと組み合わせることもできます。その分岐で判別子の条件が成立している限り、TypeScriptは絞り込みを維持します。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function bigCircle(s: Shape): boolean {
return s.kind === "circle" && s.radius > 100;
}
console.log(bigCircle({ kind: "circle", radius: 150 }));配列のfilterでの絞り込み
絞り込みはコールバックの中でも機能します。ここでは、反復処理を行いながら各図形を個別にチェックします。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
const shapes: Shape[] = [
{ kind: "circle", radius: 1 },
{ kind: "square", side: 2 }
];
shapes.forEach(s => {
if (s.kind === "circle") console.log("c", s.radius);
else console.log("s", s.side);
});switchのreturnでも型安全性を維持できる
switchですべてのcaseを処理してreturnすると、TypeScriptは各caseの結果のユニオンから、正確な戻り値の型を推論します。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function tag(s: Shape) {
switch (s.kind) {
case "circle": return s.radius;
case "square": return s.side;
}
}
console.log(tag({ kind: "circle", radius: 4 }));絞り込みのまとめ
switchとifのどちらを使う場合でも、判別子をチェックすることでメンバー固有のフィールドに安全にアクセスできます。次は、すべてのcaseが処理されることを保証します。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
return s.kind === "circle" ? Math.PI * s.radius ** 2 : s.side ** 2;
}
console.log(Math.round(area({ kind: "circle", radius: 10 })));クイックチェック:絞り込み
判別子による絞り込みについての理解度を確認しましょう。
まとめ:判別子による絞り込み
switchやifで判別子をチェックすると、ユニオンが1つのメンバーに絞り込まれ、そのメンバーに固有のフィールドだけが公開されることを学びました。早期returnや条件の組み合わせでも、絞り込みは維持されます。
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
const s: Shape = { kind: "square", side: 7 };
console.log(s.kind === "square" ? s.side : 0);よくある質問
「判別プロパティによる型の絞り込み」レッスンは無料ですか?
はい。「判別プロパティによる型の絞り込み」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。
「判別プロパティによる型の絞り込み」で何を学びますか?
TypeScriptにswitch文内のバリエーションを絞り込ませます。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
TypeScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「判別プロパティによる型の絞り込み」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このTypeScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 判別可能なユニオンの構築
- 判別プロパティによる型の絞り込み
- neverによる網羅性チェック
- ステートマシンのモデル化