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 の型システムにおいて重要な役割を果たします。適切に活用することで、より堅牢なアプリケーションの開発が可能になります。特に以下の点で有用です:
- 網羅的な型チェック
- エラーハンドリング
- 到達不可能なコードの検出
実際の開発では、これらの特徴を活かして、型安全性の高いコードを書くことができます。