never は 決して発生しない 値の型です。決して値を返さない関数(例外を投げる、または永遠にループする)や、コンパイラが不可能だと証明した分岐の型です。これは 空 の型であり、never 自身を除いて、いかなる値も never に代入できません。
ts
(): { (msg); }
(): { () {} }
never は 決して発生しない 値の型です。決して値を返さない関数(例外を投げる、または永遠にループする)や、コンパイラが不可能だと証明した分岐の型です。これは 空 の型であり、never 自身を除いて、いかなる値も never に代入できません。
(): { (msg); }
(): { () {} }
ユニオンを何もない状態まで絞り込むと、TypeScript は残った値を never 型として扱います。これを利用してすべてのケースの処理を強制できます。
type Shape =
| { kind: "circle"; r: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.r ** 2;
case "square": return s.side ** 2;
default:
// if all cases are handled, s is `never` here — assignment OK
const _exhaustive: never = s;
return _exhaustive;
}
}
ここで誰かが Shape に { kind: "triangle"; ... } を追加したのにケースを書き忘れると、default 内の s は triangle 型(never ではない)になるため、const _exhaustive: never = s は コンパイルに失敗 します。更新が必要な switch を正確に指し示してくれるのです。
function a(): void {} // returns normally, just no value
function b(): never { throw "x"; } // never returns at all
never は「すべてのケースを処理しただろうか?」を、ランタイムでの期待からコンパイル時の保証へと変えます。
これは判別可能なユニオンを安全かつ将来にわたって堅牢に扱うための鍵です。バリアントを追加すると、コンパイラが更新すべきすべての場所を列挙してくれます。