narrowing は、TypeScript が(union のような)広い型を、ランタイムのチェックに基づいてコードの分岐内でより具体的な型へと絞り込む仕組みです。コンパイラは制御フローを追跡し、それに応じて型を更新します。
ts
() {
( x === ) {
x.();
} {
x.();
}
}
typeof x === "string" // typeof guard — for primitives
x instanceof Date // instanceof — for classes
"role" in obj // in operator — property existence
Array.isArray(x) // built-in guards
if (x) { ... } // truthiness narrows out null/undefined/0/""
if (x === null) { ... } // equality narrowing
type Shape =
| { kind: "circle"; r: number }
| { kind: "square"; side: number };
function area(s: Shape) {
switch (s.kind) { // the discriminant
case "circle": return Math.PI * s.r ** 2; // s is the circle variant
case "square": return s.side ** 2; // s is the square variant
}
}
共有されているリテラルのフィールド(kind)をチェックすると、どの variant を扱っているかがコンパイラに正確に伝わり、その variant のプロパティが利用可能になります。
function isUser(x: unknown): x is User { return !!x && typeof (x as any).name === "string"; }
narrowing こそが union 型を 使えるもの にしています。型を証明した後にのみ、その型固有のメンバーへ安全にアクセスできるようにし、ランタイムのチェックをコンパイル時の保証へと変えます。
これは string | number、T | null、タグ付きの状態を扱う際に日常的に使われる仕組みです。
ジュニアからシニアまで、詳細な回答付きのIT面接質問ライブラリ。
寄付する