0Pricing
TypeScript Academy · Lekcja

Middleware błędów i typy Result

Projektowanie centralnego handlera błędów i typowanego wzorca Result, opakowywanie handlerów asynchronicznych w celu przekazywania błędów oraz zwracanie spójnych obiektów błędów

Middleware błędów i typy Result to bezpłatna lekcja TypeScript Academy na CoddyKit. To lekcja 3 z 3. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej TypeScript Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs TypeScript Academy zawiera 3 lekcji w sumie.

Wprowadzenie

Cel: Scentralizować błędy występujące w czasie działania i zwracać spójną „kopertę błędu” w formacie JSON. Należy utworzyć typ Result, asynchroniczny wrapper oraz solidne middleware obsługi błędów.

  • Rozróżnialna unia Result<T,E>
  • next(err) z asynchronicznych handlerów
  • Mapowanie Unknown na typowany błąd

Typ Result

Należy używać rozróżnialnej unii do opisywania wyników funkcji: { ok: true; value } albo { ok: false; error }. Kod wywołujący musi obsłużyć obie gałęzie.

// 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") }
}

Ujednolicony format błędu

Należy normalizować unknown do niewielkiego, przewidywalnego formatu. Nie wolno ujawniać klientom śladów stosu.

// 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" } }
}

Asynchroniczny wrapper + middleware

Należy opakować dowolny handler async, aby odrzucenia wywoływały next(err). Końcowe middleware obsługi błędów formatuje JSON tylko raz.

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)

Trasy + integracja

Należy połączyć walidację z obsługą błędów: walidacja zwraca 400 ze szczegółami, a pozostałe odrzucenia są przechwytywane przez centralne middleware.

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"))

Wskazówki

Wskazówki:

  • Szczegóły należy logować po stronie serwera, a klientowi zwracać minimalne komunikaty.
  • W usługach warto preferować typowany Result, a na granicy systemu mapować go na HTTP.
  • Nie wolno ignorować odrzuceń — zawsze należy wywoływać next(err).

Sprawdzenie błędów asynchronicznych

Szybkie sprawdzenie: Który wzorzec poprawnie przekazuje błędy asynchroniczne?

Podsumowanie

Podsumowanie: Należy używać unii Result w logice domenowej, opakowywać asynchroniczne handlery tak, aby wywoływały next, oraz formatować błędy tylko raz w końcowym middleware.

Często zadawane pytania

Czy lekcja „Middleware błędów i typy Result” jest bezpłatna?

Tak — pełny tekst „Middleware błędów i typy Result” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu TypeScript Academy, przejdź na CoddyKit PRO. Kurs TypeScript Academy zawiera 3 lekcji w sumie.

Co nauczysz się w „Middleware błędów i typy Result”?

Projektowanie centralnego handlera błędów i typowanego wzorca Result, opakowywanie handlerów asynchronicznych w celu przekazywania błędów oraz zwracanie spójnych obiektów błędów Ćwiczysz TypeScript Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć TypeScript Academy?

Nie wymagamy żadnego doświadczenia. TypeScript Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 3.

Ile czasu zajmuje lekcja „Middleware błędów i typy Result”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji TypeScript Academy?

Tak. Każda lekcja TypeScript Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Typowanie handlerów routera, Request/Response
  2. Walidacja schematów za pomocą zod i inferencja do TS
  3. Middleware błędów i typy Result
← Powrót do TypeScript Academy