概要
フロントエンド/バックエンドを問わず、APIの戻り値設計は通信だけでなくアーキテクチャ全体の信頼性に直結する。
その「形」と「一貫性」は、
- データの扱いやすさ
- エラー処理の予測性
- UI側の実装負担
すべてに影響する。
本稿では、JavaScriptで設計するAPIの戻り値とエラー構造の設計原則、
さらには成功/失敗の表現形式、パターン統一、呼び出し元の最適化について解説する。
1. 戻り値は「構造」と「意味」を分けて設計する
// ❌ データかどうかが戻り値の中身を見ないとわからない
fetch('/api/user')
.then((res) => res.json())
.then((data) => {
if (data.error) {
// エラー処理
} else {
// 成功処理
}
});
// ✅ 明示的なステータスと構造を設計
{
status: 'ok', // or 'error'
data: { name: 'Taro' }
}
- ✅
status
フラグにより成功/失敗の判断が即座に可能 - ✅
data
/error
などのフィールドが役割単位で分離
2. 成功/失敗を構造的に返すパターン(Either風)
type ApiResponse<T> =
| { ok: true; data: T }
| { ok: false; error: string };
async function fetchUser(): Promise<ApiResponse<User>> {
try {
const res = await fetch('/api/user');
if (!res.ok) throw new Error('Network error');
const json = await res.json();
return { ok: true, data: json };
} catch (e) {
return { ok: false, error: e.message };
}
}
- ✅ 戻り値を構造化することで、呼び出し側で型安全に判断可能
- ✅
try-catch
による制御が不要になるパターンも構築可能
3. エラーはメッセージではなく「構造」で返す
// ❌ 単なる文字列だけでは処理不能
{ ok: false, error: "Invalid parameter" }
// ✅ フィールドベースで構造化
{
ok: false,
error: {
code: 'INVALID_PARAMETER',
message: 'User ID must be a number.',
field: 'userId'
}
}
- ✅ フロントエンド側でフィールド単位のエラーハンドリングが可能
- ✅ i18n化・UIバリデーション連携も容易になる
4. API呼び出し側の最適化:分岐の一元化
const res = await fetchUser();
if (!res.ok) {
showError(res.error);
return;
}
renderUser(res.data);
- ✅ 成功/失敗の制御が明確・簡潔
- ✅ 複数パターンに拡張する場合も判定条件が安定する
5. REST/GraphQL問わず設計に共通する指針
要素 | 設計方針 |
---|---|
成功応答 | 明示的な status: 'ok' / ok: true
|
失敗応答 | エラー構造 { code, message, field }
|
戻り値の型 | Union型で成功/失敗を分離 |
例外の扱い | 可能な限り throw より Result型 を優先 |
呼び出し側 |
if (!res.ok) によるフラットな分岐構造
|
設計判断フロー
① APIの成功/失敗をどう判断する? → 明示的にステータス or okフラグで表現
② エラーはどこで使われるか? → UI連携 or ログ出力なら構造化すべき
③ 呼び出し側でtry-catchが多発していないか? → 戻り値ベースの設計を導入
④ 型安全に処理したいか? → Union型による成功/失敗モデルへ移行
⑤ 今後の拡張(複数エラー、バリデーション)に備える? → エラー構造を定義
よくあるミスと対策
❌ APIエラーを throw
に任せすぎて制御が複雑化
→ ✅ 「失敗もレスポンス」として扱い、構造的に処理
❌ 成功時と失敗時の戻り値の構造が不一致で呼び出し側がバグる
→ ✅ 必ず status
/ ok
を軸に共通構造を設計
❌ フロントでエラーメッセージの内容を分岐処理してしまう
→ ✅ エラーコードを導入し、UI処理を安定化させる
結語
API設計において最も重要なのは「通信」ではない。
それは**“データと失敗を同じ構造で安全に管理し、UI・ロジック・保守性を整合的に設計すること”**である。
- 成功と失敗を明確に分離した構造で返す
- 例外ではなく構造的レスポンスで制御する
- フロントエンドとの接続面において、予測可能性と統一感を保証する
JavaScriptにおけるAPI設計とは、
“返すデータだけでなく、それをどう扱わせるかまでをデザインする構造戦略である。”