TypeScript и Node.js
Дальше: TypeORM · Асинхронность · Обработка ошибок · Форматы и подключение
Node.js выполняет скомпилированный JavaScript; TypeScript задаёт контракты для HTTP API, файлов, БД и доменной логики. DTO (Data Transfer Object) на границе сети отделяют JSON от доменной модели — см. паттерны. Один язык на frontend и backend упрощает общие типы — при дисциплине слоёв. Удобный порядок — первая программа, форматы и подключение, эта статья, TypeORM.
Runtime Node: раздел Node в JS. Монорепо — Экосистема и архитектура TypeScript.
TypeScript на backend
| Выгода | Пример |
|---|---|
| Контракт API | CreateUserDto и UserEntity — разные типы |
| Рефакторинг | переименование поля ловит все handlers |
| CI | tsc --noEmit на каждый PR |
| Общие типы | пакет @myorg/contracts в monorepo |
TS не отменяет валидацию тела запроса: JSON из сети — unknown до проверки — Рекомендации по разработке на TypeScript.
Минимальный проект
mkdir my-api && cd my-api
npm init -y
npm i -D typescript @types/node tsx
npx tsc --init
tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"strict": true,
"outDir": "dist",
"rootDir": "src",
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
package.json:
{
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsx watch src/index.ts",
"typecheck": "tsc --noEmit"
}
}
Разбор:
NodeNext— ESM/CJS по правилам Node 20+ — Форматы и подключение TypeScript.tsx— dev без ручной пересборки; production —tsc+node.
Слои — DTO, domain, persistence
Код ITЗагрузка примера кода…
Разбор:
- DTO отражает тело запроса; domain — то, с чем работает сервис.
- Поля БД (
created_at) не протекают в API без маппера.
Сервис и Result
Код ITЗагрузка примера кода…
Подробнее Result — Обработка ошибок в TypeScript.
Handler в стиле Express
Код ITЗагрузка примера кода…
Разбор:
body—unknownдо guard.- Ответ типизирован union — клиент на TS может переиспользовать тип.
NestJS, Fastify — те же принципы DTO; декораторы — Декораторы в TypeScript.
Файлы — fs/promises
import { readFile, writeFile } from "node:fs/promises";
import path from "node:path";
async function loadConfig(dir: string): Promise<Record<string, string>> {
const file = path.join(dir, "config.json");
const raw = await readFile(file, "utf8");
const data: unknown = JSON.parse(raw);
if (typeof data !== "object" || data === null) {
throw new Error("Invalid config");
}
return data as Record<string, string>;
}
Разбор:
@types/nodeдаёт типы дляfs,path,crypto.- Async — Асинхронное программирование в TypeScript.
Структура backend-проекта
src/
├── index.ts # bootstrap
├── app.ts # HTTP app
├── modules/
│ └── users/
│ ├── user.service.ts
│ ├── user.routes.ts
│ └── user.types.ts
└── shared/
├── errors.ts
└── types/
| Слой | Ответственность |
|---|---|
| routes / controllers | HTTP, статусы |
| services | бизнес-логика, Result |
| repositories | БД — TypeORM |
Переменные окружения
function requireEnv(name: string): string {
const v = process.env[name];
if (!v) throw new Error(`Missing env: ${name}`);
return v;
}
const port = Number(requireEnv("PORT"));
Для сложных конфигов — Zod-схема env — Рекомендации по разработке на TypeScript.
CI
- run: npm ci
- run: npm run typecheck
- run: npm test
- run: npm run build
Разбор:
typecheckиbuild— разные шаги, если bundler не вызываетtsc— Экосистема и архитектура TypeScript.
Частые ошибки
| Ошибка | Что делать |
|---|---|
req.body as Dto | type guard |
| Один тип на DTO и ORM entity | разделить + mapper |
CommonJS/import без .js | NodeNext + расширение в import |
Нет @types/node | devDependency |
any в middleware | типизировать Request augmentation |
Практика
- Поднимите API с одним
POST /usersи guard тела. - Разделите
CreateUserDto,User, ответ API. - Добавьте
typecheckв CI. - Прочитайте файл конфига через
fs/promisesсunknown+ проверкой. - Верните
409приconflictизServiceResult.
Смежные статьи
- Подключение · Async · Ошибки · TypeORM
- Экосистема · Компиляция
- Простые приложения на TypeScript — мини-проекты