Prompt

Tsのnever型はいつ使えばいい?

おっと、ついに**「虚無(never)」の型に辿り着いたね!

TypeScriptにおける never 型は、情報工学的に言うと「ボトム型(Bottom Type)」。つまり、「いかなる値も持つことができない型」**なんだ。

一見すると「値を持てない型なんて、いつ使うんだ?」と思うかもしれないけど、キミが好きな「制限による安全性」を極めるなら、これほど頼もしい守護神はいないよ。

never を使いこなすべき「3つの聖域」を解剖しよう!


1. 網羅性チェック (Exhaustiveness Check)

これが最もコンストラティブな使い方だよ。

例えば、キミがTiptapの機能を switch 文で分岐させているとする。将来、新しい機能を追加した時に「実装し忘れ」をコンパイルエラーで教えてくれる魔法の仕組みだ。

TypeScript

type Feature = "bold" | "italic" | "image";

function handleFeature(feature: Feature) {
  switch (feature) {
    case "bold": return "太字";
    case "italic": return "斜体";
    case "image": return "画像";
    default:
      // ここがポイント!
      // もし将来 Feature に "link" が追加されたら、
      // feature は "link" 型になり、never 型に代入できなくなってエラーが出る。
      const _exhaustiveCheck: never = feature;
      return _exhaustiveCheck;
  }
}

これは、**「すべての道(ケース)を塞いだはずだ。もしここへ到達する値があるなら、それは論理的な矛盾だ」**とコンパイラに宣言しているんだ。心地よい制限だろ?


2. 「絶対に返らない」関数の戻り値

関数が最後まで実行されない、つまり「呼び出し元に制御が戻ることが絶対にない」ことを明示する時に使うよ。

  • 例外を投げる関数: throw new Error() で終わる。

  • 無限ループする関数: プログラムが終了するまで動き続ける。

TypeScript

function reportFatalError(): never {
  throw new Error("システムに致命的な不協和音が走りました!");
}

これを void(何も返さない)ではなく never(返ることがない)にすることで、それ以降のコードが**デッドコード(実行されない領域)**であることをコンパイラが理解し、最適化に繋がるんだ。


3. 型パズルでの「除外」フィルタ

キミが興味を持っていた「型パズル」の世界では、never は**「消しゴム」**として活躍するよ。

条件に合わない型を never に飛ばすと、その型は Union 型の中から消滅するんだ。

TypeScript

// T から string 以外の型を除去するパズル
type OnlyStrings<T> = T extends string ? T : never;

type Result = OnlyStrings<string | number | boolean>; 
// -> 結果は string 型だけになる!(number と boolean は never になり、消える)

💡 豆知識:neverany の対極性

  • any: 何でも受け入れる「混沌(エントロピー最大)」

  • never: 何も受け入れない「虚無(秩序の極致)」

never を適切に配置することは、プログラムの宇宙に**「絶対にありえない境界線」**を引くことなんだ。


🌟 結論:never は「規律の証」

キミが「自由を制限することが心地よい」と感じるなら、never 型を愛せるはずだ。

それは、「論理的な矛盾を許さない」というキミの強い意志を型システムに刻み込む行為だからね。

「この変数にはもう何も入る余地はない」と確信したとき、そこに never が現れる。美しくないかい?😉

次は、この never を使って、さらに複雑な 「テンプレートリテラル型を使った高度なバリデーションパズル」 に挑戦してみる?それとも、別の型の深淵へ行く?