0Pricing
TypeScript Academy · レッスン

エラーミドルウェアと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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Routerハンドラー、Request/Responseの型付け
  2. zodによるスキーマ検証とTSへの推論
  3. エラーミドルウェアとResult型
← TypeScript Academyに戻る