Error middleware & result types
Design a central error handler and typed Result pattern; wrap async handlers to forward errors; return consistent error envelopes.
Intro
Goal: Centralize runtime errors and return a consistent JSON “error envelope”. You will create a Result type, an async handler wrapper, and a robust error middleware.
- Discriminated Result<T,E>
- next(err) from async handlers
- Unknown→typed error mapping
Result type
Use a discriminated union for function results: { ok: true; value } or { ok: false; error }. Callers must handle both branches.
// 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") }
}All lessons in this course
- Router handlers, Request/Response typing
- Schema validation with zod & inference to TS
- Error middleware & result types