TypeScriptのnever型は「決して発生しない値の型」を表現する特殊な型です。この記事では、never型の基本的な概念から実践的な活用方法まで、具体的な例を交えて解説します。

never型とは

never型は、値を持つことができない型で、以下のような状況で使用されます:

1. 絶対に返り値を返さない関数

2. 常にエラーをスローする関数

3. 無限ループする関数

基本的な使用例

// エラーをスローする関数
function throwError(message: string): never {
    throw new Error(message);
}

// 無限ループする関数
function infiniteLoop(): never {
    while (true) {
        // 処理
    }
}

never型の実践的な活用

1. 網羅的なtype checking

type Shape = 'circle' | 'square' | 'triangle';

function processShape(shape: Shape) {
    switch (shape) {
        case 'circle':
            // 円の処理
            break;
        case 'square':
            // 四角の処理
            break;
        case 'triangle':
            // 三角の処理
            break;
        default:
            // 全てのケースを網羅している場合、
            // この行は実行されることはない
            const exhaustiveCheck: never = shape;
            return exhaustiveCheck;
    }
}

2. エラーハンドリング

function handleError(error: Error): never {
    console.error(error.message);
    throw error;
}

function processData(data: string | null) {
    if (data === null) {
        handleError(new Error('データが存在しません'));
    }
    // データの処理
    return data.toUpperCase();
}

3. 型の絞り込み

type UserResponse = { status: 'success'; data: { name: string } } | { status: 'error'; message: string };

function processResponse(response: UserResponse) {
    if (response.status === 'success') {
        console.log(response.data.name);
    } else if (response.status === 'error') {
        console.error(response.message);
    } else {
        // response の型が never になる
        const unreachable: never = response;
    }
}

never型の利点

1. 型安全性の向上: コンパイル時に潜在的なエラーを検出できます。

2. コードの完全性: すべてのケースが処理されていることを保証します。

3. メンテナンス性: 新しい型が追加された際に、対応が必要な箇所を容易に特定できます。

プラクティス

// 実践的な例:API エラーハンドリング
type ApiError = {
    type: 'validation' | 'network' | 'auth';
    message: string;
};

function handleApiError(error: ApiError): never {
    switch (error.type) {
        case 'validation':
            throw new Error(`Validation error: ${error.message}`);
        case 'network':
            throw new Error(`Network error: ${error.message}`);
        case 'auth':
            throw new Error(`Authentication error: ${error.message}`);
        default:
            const exhaustiveCheck: never = error.type;
            return exhaustiveCheck;
    }
}

まとめ

never型は TypeScript の型システムにおいて重要な役割を果たします。適切に活用することで、より堅牢なアプリケーションの開発が可能になります。特に以下の点で有用です:

  • 網羅的な型チェック
  • エラーハンドリング
  • 到達不可能なコードの検出

実際の開発では、これらの特徴を活かして、型安全性の高いコードを書くことができます。