エラーミドルウェアとResult型
中央のエラーハンドラーと型付きResultパターンを設計し、非同期ハンドラーをラップしてエラーを転送し、一貫したエラー形式を返します
「エラーミドルウェアとResult型」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン3/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全3レッスンが含まれています。
はじめに
目標:実行時エラーを一元化し、一貫した JSON の「エラーエンベロープ」を返します。Result 型、async ハンドラーラッパー、堅牢なエラーミドルウェアを作成します。
- 判別可能な Result<T,E>
- async ハンドラーからの next(err)
- Unknown から型付きエラーへのマッピング
Result 型
関数の戻り値には判別共用体を使います。戻り値は { ok: true; value } または { ok: false; error } のいずれかです。呼び出し側では両方の分岐を処理する必要があります。
// Result pattern for services and controllers
export type Ok<T> = { ok: true; value: T }
export type Err<E> = { ok: false; error: E }
export type Result<T, E = string> = Ok<T> | Err<E>
export const ok = <T>(value: T): Ok<T> => ({ ok: true, value })
export const err = <E>(error: E): Err<E> => ({ ok: false, error })
// Example usage
async function getUserName(id: string): Promise<Result<string, "NOT_FOUND" | "DB">> {
if (id === "missing") return err("NOT_FOUND")
try { return ok("Ada") } catch { return err("DB") }
}エラーエンベロープ
unknown を小さく予測可能なエンベロープに正規化します。クライアントにスタックトレースを漏らさないようにします。
// Canonical error envelope
export type ErrorEnvelope = {
error: string
code?: string
details?: unknown
}
export function mapError(u: unknown): ErrorEnvelope {
if (u instanceof Error) return { error: u.message }
if (typeof u === "string") return { error: u }
try { return { error: JSON.stringify(u) } } catch { return { error: "Unknown error" } }
}Async ラッパーとミドルウェア
任意の async ハンドラーをラップし、rejection 時に next(err) を呼び出すようにします。最後のエラーミドルウェアで JSON を一度だけ整形します。
import express, { Request, Response, NextFunction } from "express"
export const asyncHandler = <P, ResBody, ReqBody, Query>(fn: (req: Request<P, ResBody, ReqBody, Query>, res: Response<ResBody>, next: NextFunction) => Promise<unknown>) => {
return (req: Request<P, ResBody, ReqBody, Query>, res: Response<ResBody>, next: NextFunction) => {
Promise.resolve(fn(req, res, next)).catch(next)
}
}
export function errorMiddleware(err: unknown, _req: Request, res: Response, _next: NextFunction) {
const env = mapError(err)
const status = env.code === "NOT_FOUND" ? 404 : 500
res.status(status).json(env)
}
// Usage
// app.get("/", asyncHandler(async (req, res) => { throw new Error("boom") }))
// app.use(errorMiddleware)ルートと統合
バリデーションとエラー処理を組み合わせます。バリデーションでは詳細付きの 400 を返し、それ以外の rejection は中央ミドルウェアで捕捉します。
import express from "express"
import { z } from "zod"
import { asyncHandler, errorMiddleware } from "./errors"
const createUserSchema = z.object({ name: z.string().min(1) })
const app = express()
app.use(express.json())
app.post("/users", asyncHandler(async (req, res) => {
const parsed = createUserSchema.safeParse(req.body)
if (!parsed.success) {
res.status(400).json({ error: "Invalid body", details: parsed.error.format() })
return
}
res.status(201).json({ id: "u_1", name: parsed.data.name })
}))
app.use(errorMiddleware)
app.listen(3000, () => console.log("http://localhost:3000"))ヒント
ヒント:
- サーバー側では詳細をログに記録し、クライアントには最小限のメッセージを返します。
- サービスでは型付きの Result を優先し、境界で HTTP に変換します。
- rejection を握りつぶさず、必ず
next(err)を呼び出します。
非同期エラーの確認
確認問題:非同期エラーを正しく転送するパターンはどれですか?
まとめ
まとめ:ドメインロジックには Result 共用体を使い、async ハンドラーをラップして next を呼び出し、最後のミドルウェアでエラーを一度だけ整形します。
よくある質問
「エラーミドルウェアとResult型」レッスンは無料ですか?
はい。「エラーミドルウェアとResult型」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全3レッスンが含まれています。
「エラーミドルウェアとResult型」で何を学びますか?
中央のエラーハンドラーと型付きResultパターンを設計し、非同期ハンドラーをラップしてエラーを転送し、一貫したエラー形式を返します ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
TypeScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/3です。
「エラーミドルウェアとResult型」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このTypeScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Routerハンドラー、Request/Responseの型付け
- zodによるスキーマ検証とTSへの推論
- エラーミドルウェアとResult型