概要
エラーハンドリングは「落ちたらcatchすればいい」ではない。
それは**“予期される失敗をコントロール下に置き、予期されない例外を安全に隔離するための設計戦略”**である。
JavaScriptは例外処理が柔軟な分、無秩序なtry-catchや雑なnullチェックが多発し、
保守性の低いコードになりがちである。
本稿では、try-catchの責務分離、throw戦略、null/undefined許容の境界設計、エラーオブジェクトの設計までを含む、構造的なエラーハンドリングの戦略を解説する。
1. try-catch の最小粒度原則
// ❌ 粗すぎる例外ハンドリング(原因不明)
try {
const user = JSON.parse(json);
const name = user.name.toUpperCase();
saveToDB(name);
} catch (e) {
console.error('Failed');
}
// ✅ 粒度を最小化
let user;
try {
user = JSON.parse(json);
} catch (e) {
throw new Error('Invalid JSON format');
}
- ✅ 例外は「どの処理で失敗したか」が明示されるように
- ✅ 一つのtryブロックには一つの責務
2. throw戦略とカスタムエラー設計
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateName(name) {
if (!name) throw new ValidationError('Name is required');
}
- ✅
throw
は構造化された情報を投げる - ✅
Error
クラスの継承により、型や原因でcatchを分岐可能
3. null / undefined の安全設計
// ❌ 曖昧なnull処理
if (user && user.profile && user.profile.avatar) {
show(user.profile.avatar);
}
// ✅ オプショナルチェーン
show(user?.profile?.avatar);
- ✅
?
を使うことで**意図的に「なければ無視」**を表現 - ✅ ただし、「なければ失敗すべき」文脈では明示的な
throw
を使う
4. 関数としての失敗表現(Either風)
function parseJSON(str) {
try {
return { ok: true, value: JSON.parse(str) };
} catch (e) {
return { ok: false, error: e };
}
}
const result = parseJSON(input);
if (result.ok) {
use(result.value);
} else {
log(result.error);
}
- ✅ 例外を外に出さず、「結果として返す」ことで呼び出し側に制御権
- ✅ 副作用の少ないAPI設計に有効
5. UI/UXにおけるエラー分離(境界設計)
try {
const user = await fetchUser();
render(user);
} catch (e) {
renderErrorMessage('ユーザーの取得に失敗しました');
}
- ✅ UIとロジックの責務を明確に
- ✅ catchブロックはユーザーに示す最小限のUIエラーに限定
設計判断フロー
① このエラーは「予期される失敗」か? → null/undefined or 値で返す
② 「例外」として投げるべきか? → 開発者のバグ or 実行時異常の場合のみ
③ try-catch の粒度は適切か? → 単一の責務だけを囲んでいるか
④ catch内でロギング + 再throwが必要か? → 処理の境界を意識する
⑤ エラーオブジェクトは構造的か? → name/type/message を設計済か
よくあるミスと対策
❌ try 内部で複数の処理を抱え、catchでは何が原因か不明
→ ✅ tryの粒度を責務単位で分割し、catchで明示
❌ throw new Error('X is missing')
をただの文字列で処理
→ ✅ カスタムErrorクラスで分類と構造化を
❌ すべてのnullを例外としてthrowし、UXが壊滅
→ ✅ nullは"欠けてもよい"設計の場合、静かに無視 or fallbackする
結語
エラーハンドリングは「エラーをキャッチする技法」ではない。
それは**“失敗と異常を制御構造として設計し、責務とUXを守るための安全装置”**である。
- try-catch の粒度を絞り、catch の責務を明確に
- throw は例外であり、エラーではない
- null許容と例外制御を文脈ごとに設計し分離する
JavaScriptにおけるエラーハンドリングとは、
“失敗の責任と通知の設計を通じて、堅牢性と理解可能性を両立させるための戦略である。”