# Как построить надежный API на Express и TypeScript: пошаговое руководство

Источник: https://www.youtube.com/watch?v=bYgphDEWwvs
Канал: freeCodeCamp.org
Опубликовано: 24.07.2026

---

Использование TypeScript в связке с Express значительно повышает безопасность, масштабируемость и удобство поддержки серверных приложений. В данном руководстве Рэйчел, преподаватель платформы Scrimba и автор видео на канале freeCodeCamp.org, пошагово разбирает процесс создания типизированного API для приюта домашних животных.

## 🛠 Настройка окружения и установка зависимостей
[[JUMP:02:08]]

Процесс начинается со стандартной инициализации Node.js проекта с помощью команды `npm init -y` [02:11]. Для работы в среде TypeScript недостаточно просто установить Express; необходимо также добавить типы, так как сама библиотека написана на чистом JavaScript.

Для подготовки рабочего окружения автор устанавливает следующие пакеты:

*   **Express**: основной фреймворк (устанавливается как обычная зависимость) [02:23].
*   **TypeScript**: компилятор и инструменты языка (dev-dependency) [02:49].
*   **@types/express**: определения типов для Express, позволяющие TypeScript понимать такие объекты, как `Request` и `Response` [03:03].
*   **tsconfig**: специальный пакет с готовыми конфигурациями (в данном случае для Node 20) [03:42].

Конфигурация TypeScript осуществляется через файл `tsconfig.json`. Вместо ручного написания всех правил Рэйчел рекомендует расширять готовые пресеты с помощью поля `extends` [04:08]. В `compilerOptions` критически важно указать:

*   `rootDir`: директория `source`, где будет храниться исходный код на TypeScript [04:35].
*   `outDir`: директория `dist`, куда компилятор будет помещать готовый JavaScript-код для запуска в Node.js [04:49].

## 🚀 Создание первого сервера и компиляция
[[JUMP:07:12]]

Первый файл сервера создается с расширением `.ts` (например, `index.ts`). На этом этапе Рэйчел демонстрирует импорт типов напрямую из библиотеки: `import express, { Express, Request, Response } from 'express'` [09:02]. Хотя TypeScript часто способен сам вывести типы (например, для экземпляра приложения `app`), явное указание типа `Express` помогает закрепить навыки работы с системой типов [09:28].

Поскольку Node.js не умеет исполнять TypeScript напрямую, код необходимо скомпилировать. Для этого используется встроенный компилятор `npx tsc` [10:49]. Он анализирует проект и создает папку `dist` с JS-файлами. Только после этого сервер можно запустить командой `node dist/index.js` [11:43].

Чтобы упростить процесс разработки, Рэйчел предлагает настроить скрипты в `package.json` [15:54]:

*   `build`: выполняет `tsc`.
*   `start`: объединяет команды через оператор `&&`, сначала компилируя код, а затем запуская сервер (`tsc && node dist/index.js`) [17:01].

## 🐾 Моделирование данных и типизация сущностей
[[JUMP:19:25]]

Для создания реального API требуется структура данных. В примере рассматривается приют для животных, где у каждого питомца есть набор характеристик. Автор переносит данные в отдельный файл `source/data/pets.ts` для соблюдения модульности [19:51].

Ключевым моментом здесь является создание кастомного типа `Pet` [20:46]. В процессе разработки типа Рэйчел обращает внимание на использование специфических возможностей TypeScript:

*   **Optional properties**: поля, помеченные вопросительным знаком (например, `adoptionDate?`), так как не все животные в приюте уже обрели дом [23:00].
*   **Union types**: для поля `microchipId`, которое может быть либо строкой, либо `null` [23:12].
*   **Вложенные объекты**: для медицинских записей (`medicalRecord`), содержащих массивы строк и числа [22:07].

## 🔍 Глубокая типизация Request и Response
[[JUMP:33:01]]

Одной из самых мощных функций TypeScript в Express является использование дженериков (generics) для объектов запроса и ответа. Типы `Request` и `Response` позволяют точно описать, что именно сервер ожидает получить и что он отправит клиенту.

По словам Рэйчел, дженерик для `Response` позволяет задать структуру тела ответа (Response Body) [33:27]. Например, если маршрут возвращает список животных, тип будет выглядеть как `Response<Pet[]>` [34:22]. Это гарантирует, что разработчик не отправит ошибочные данные.

Объект `Request` еще более сложен и включает четыре основных параметра [45:11]:

1.  `P`: параметры пути (Path Params, например, `:id`).
2.  `ResBody`: тело ответа.
3.  `ReqBody`: тело запроса (для POST/PUT методов).
4.  `ReqQuery`: параметры строки запроса (Query Params).

## 🧪 Фильтрация и параметры запроса
[[JUMP:41:31]]

Разработка функционала фильтрации (например, по виду животного или статусу адаптации) требует особого внимания к типам. Рэйчел подчеркивает, что параметры из `req.query` всегда приходят в виде строк [48:56]. Если API должно фильтровать данные по булеву значению (`adopted`) или числу (`age`), эти значения необходимо парсить вручную.

Для удобства автор создает отдельный тип `PetQueryParams`, где описывает все возможные фильтры [48:00]:

*   `species`: строка (например, "cat" или "dog").
*   `adopted`: литеральный тип `"true" | "false"`, что гораздо строже, чем просто `string` [49:10].
*   `minAge` / `maxAge`: строки, которые позже конвертируются в числа для сравнения [52:24].

## 🏗 Рефакторинг: Роутеры и Контроллеры
[[JUMP:54:05]]

Когда файл `index.ts` становится слишком объемным («chunkier», как говорит Рэйчел), проект необходимо реструктурировать. Ведущая демонстрирует стандартный для Express подход разделения ответственности [54:25]:

1.  **Routes**: определяют пути (endpoints) и используют `express.Router()`. Здесь важно импортировать тип `Router` для типизации самого объекта роутера [55:43].
2.  **Controllers**: содержат бизнес-логику и обработчики. При переносе логики из роутера в контроллер необходимо также переносить и все связанные типы данных и запросов [59:34].

Такой подход делает код чистым и масштабируемым, сохраняя при этом полную типизацию всех связей.

## 🛡 Использование Middleware с TypeScript
[[JUMP:1:03:13]]

Middleware (промежуточное ПО) — это функции, которые выполняются между получением запроса и отправкой ответа. В TypeScript для них предусмотрен специальный тип `NextFunction` [1:04:13].

Рэйчел приводит два практических примера кастомных middleware:

*   **Валидация ID**: проверка, является ли переданный ID числом, с помощью регулярного выражения. Если проверка не проходит, сервер возвращает ошибку 400 еще до того, как запрос попадет в основной контроллер [1:04:39].
*   **Простая авторизация (`pleaseAuth`)**: имитация проверки доступа, где пользователь обязан передать query-параметр `password=please`. В противном случае возвращается статус 401 (Unauthorized) [1:09:15].

В завершение курса Рэйчел отмечает, что хотя использование TypeScript добавляет «лишние шаги» (вроде установки типов для сторонних библиотек, таких как `cors`), это окупается за счет раннего обнаружения ошибок и автоматических подсказок в редакторе (Intellisense) [1:13:44].