TypeScript Academy · レッスン

never型と不可能な状態

neverを使って、到達不能なコードや不可能な値をモデル化します。

レッスン 2/413 ステップ

「never型と不可能な状態」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。

never 型

never は空の型であり、決して発生しない値を表します。never 自体を除き、どの値も never には代入できません。発生してはならない状況を示すために使われます。

// You cannot create a value of type never
function crash(): never {
  throw new Error('boom');
}
try { crash(); } catch (e) { console.log('caught'); }

決して戻らない関数

常に throw する関数は正常に戻ることがないため、戻り値の型は never になります。これにより、呼び出し元とコンパイラーに、ここで実行が停止することを伝えます。

function fail(message: string): never {
  throw new Error(message);
}
try { fail('invalid'); } catch (e) { console.log('handled'); }

無限ループは never を返す

無限ループを持つ関数も決して戻らないため、同様に never として型付けされます。コンパイラーは、その先に制御フローが続かないことを認識します。

function listen(): never {
  while (true) {
    // forever
    break; // (break added so the demo terminates)
  }
  throw new Error('stopped');
}
console.log('listen has return type never');

never と void の違い

never と void を混同しないでください。void 型の関数は戻ります(有用な値を返さないだけです)。never 型の関数はまったく戻りません。例外を投げるか、永遠にループします。

function logIt(): void {
  console.log('done'); // returns normally
}
function abort(): never {
  throw new Error('stop'); // never returns
}
logIt();
try { abort(); } catch (e) { console.log('ok'); }

網羅性チェックで never を使う

never の最も実用的な用途は、網羅性チェックです。switch の default で、変数を never に代入します。すべてのケースが処理されていれば、その変数はすでに never なのでコンパイルできます。

type Shape = 'circle' | 'square';

function area(s: Shape): string {
  switch (s) {
    case 'circle': return 'pi r^2';
    case 'square': return 'a^2';
    default:
      const _check: never = s; // ok: all handled
      return _check;
  }
}
console.log(area('square'));

処理漏れの検出

誰かが新しいユニオンメンバーを追加したのにケースの追加を忘れると、残った値はもはや never ではないため、代入のコンパイルに失敗します。never チェックによって、気付かれない処理漏れが明確なエラーになります。

type Shape = 'circle' | 'square' | 'triangle';
// If 'triangle' case is missing, assigning s to never
// would error: 'triangle' is not assignable to never.
console.log('Add a case for every member');

不可能なユニオン分岐で never を使う

型の絞り込みによってすべての可能性が取り除かれると、残りの型は never になります。コンパイラーはその分岐に到達できないことを認識するため、ロジックの誤りを発見できる場合があります。

function check(x: string | number): void {
  if (typeof x === 'string') {
    console.log('string');
  } else if (typeof x === 'number') {
    console.log('number');
  } else {
    // x is never here
    console.log('unreachable');
  }
}
check('hi');

ボトム型としての never

never はボトム型です。存在しない値はどの型にも矛盾なく適合するとみなせるため、他のすべての型に代入できます。これが、throw を任意の式の位置に置ける理由です。

function getOrThrow(v: string | null): string {
  return v ?? fail();
}
function fail(): never {
  throw new Error('missing');
}
console.log(getOrThrow('value'));

ユニオンを never に絞り込む

条件付き型やマップ型では、never は「これを削除する」という働きをします。never とのユニオンは何も変えません。T | never は単に T です。そのため、フィルタリングに自然に利用できます。

type Keep<T> = T extends string ? T : never;
type R = Keep<'a' | 1 | 'b'>; // 'a' | 'b'
const x: R = 'a';
console.log(x);

不可能な状態をモデル化する

オブジェクトの形状に never を使うと、許可されない組み合わせを表現できないようにできます。ここでは、型によって「読み込み中」の状態がデータを同時に持てないようにしています。

type State =
  | { status: 'loading'; data?: never }
  | { status: 'ready'; data: number };

const s: State = { status: 'ready', data: 7 };
console.log(s);

never によるリファクタリングの安全性向上

never による網羅性チェックは、ケースが不足すると失敗するため、リファクタリングを安全にします。ユニオンを拡張すると、更新が必要なすべての箇所をコンパイラーが示してくれます。

type Cmd = 'start' | 'stop';
function run(c: Cmd): string {
  if (c === 'start') return 'starting';
  if (c === 'stop') return 'stopping';
  const _x: never = c;
  return _x;
}
console.log(run('start'));

理解度チェック

never 型の理解度を確認しましょう。

振り返り: never

neverについて、次のことを学びました。

  • 空の型であり、never型の値は存在しません。
  • 例外をスローするか、無限ループする関数の戻り値の型です。
  • switch の default 節における網羅性チェックを可能にします。
  • 到達不能な絞り込み分岐に現れ、型の論理ではユニオン型をフィルタリングします。

次はvoidを取り上げ、どのように異なるのかを見ていきます。

function assertNever(x: never): never {
  throw new Error('Unexpected: ' + String(x));
}
console.log('assertNever guards exhaustiveness');
無料で開始

AI チューターと学ぶ TypeScript — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
101
レッスン
352

よくある質問

「never型と不可能な状態」レッスンは無料ですか?

はい。「never型と不可能な状態」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。

「never型と不可能な状態」で何を学びますか?

neverを使って、到達不能なコードや不可能な値をモデル化します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

TypeScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「never型と不可能な状態」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このTypeScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. unknownとanyを理解する
  2. never型と不可能な状態
  3. 関数におけるvoid型
  4. unknownの型安全な扱い
← TypeScript Academyに戻る