TypeScript Academy · Урок

Промежуточное ПО для ошибок и типы результатов

Спроектируйте централизованный обработчик ошибок и типизированный шаблон Result; оборачивайте асинхронные обработчики для передачи ошибок и возвращайте единообразные оболочки ошибок.

Урок 3 из 38 шагов

«Промежуточное ПО для ошибок и типы результатов» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 3 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 3 уроков всего.

Введение

Цель: централизовать ошибки времени выполнения и возвращать единый JSON-объект ошибки. Вы создадите тип результата, обёртку асинхронного обработчика и надёжное промежуточное ПО обработки ошибок.

  • Размеченный результат<T,E>
  • Вызов next(err) из асинхронных обработчиков
  • Сопоставление неизвестных значений с типизированными ошибками

Тип результата

Используйте размеченное объединение для результатов функций: { 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") }
}

Обёртка ошибки

Приводите неизвестные значения к небольшой предсказуемой обёртке. Не раскрывайте трассировки стека клиентам.

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

Асинхронная обёртка и промежуточное ПО

Оберните любой асинхронный обработчик так, чтобы отклонённые обещания вызывали 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 с подробностями, а остальные отклонённые обещания перехватывает центральное промежуточное ПО.

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

Советы

Советы:

  • Записывайте подробности на сервере, а клиенту возвращайте минимальные сообщения.
  • Предпочитайте типизированный результат в службах и преобразуйте его в HTTP-ответ на границе системы.
  • Никогда не подавляйте отклонённые обещания — всегда вызывайте next(err).

Проверка асинхронных ошибок

Быстрая проверка: какой шаблон правильно передаёт асинхронные ошибки?

Повторение

Повторение: используйте объединение результата для логики предметной области, оборачивайте асинхронные обработчики для вызова next и форматируйте ошибки один раз в финальном промежуточном ПО.

Можно начать бесплатно

Изучай TypeScript с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
101
Уроки
352

Часто задаваемые вопросы

Урок «Промежуточное ПО для ошибок и типы результатов» бесплатный?

Да — полный текст урока «Промежуточное ПО для ошибок и типы результатов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 3 уроков всего.

Чему я научусь в уроке «Промежуточное ПО для ошибок и типы результатов»?

Спроектируйте централизованный обработчик ошибок и типизированный шаблон Result; оборачивайте асинхронные обработчики для передачи ошибок и возвращайте единообразные оболочки ошибок. Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать TypeScript Academy?

Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 3.

Сколько времени занимает урок «Промежуточное ПО для ошибок и типы результатов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке TypeScript Academy?

Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Обработчики маршрутизатора, типизация Request/Response
  2. Проверка схем с zod и вывод типов в TS
  3. Промежуточное ПО для ошибок и типы результатов
← Назад к TypeScript Academy