Введение: почему TypeScript для REST API?
Современная веб-разработка немыслима без четких и масштабируемых API. TypeScript, являясь строго типизированной надстройкой над JavaScript, позволяет создавать надежные REST API с минимальным количеством ошибок времени выполнения. В этой статье мы на практике, шаг за шагом, создадим полноценный REST API на TypeScript с использованием популярного фреймворка Express. Весь процесс займет у вас не более 30 минут, а результат будет готов к использованию в реальных проектах.
Мы разберем: инициализацию проекта, настройку TypeScript, создание маршрутов, работу с middleware, обработку ошибок и тестирование эндпоинтов. Все примеры кода вы сможете сразу запустить и адаптировать под свои задачи.
Шаг 1: Инициализация проекта и установка зависимостей
Первым делом создадим новую директорию для проекта и инициализируем его. Откройте терминал и выполните:
mkdir my-ts-api
cd my-ts-api
npm init -y
Теперь установим необходимые пакеты:
npm install express
npm install -D typescript @types/node @types/express ts-node nodemon
Создадим файл конфигурации TypeScript:
npx tsc --init
Отредактируйте tsconfig.json, включив следующие опции:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}
Добавьте скрипты в package.json:
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "nodemon --exec ts-node src/index.ts"
}
Шаг 2: Создание базовой структуры и первого эндпоинта
Создайте папку src и внутри нее файл index.ts. Начнем с простого сервера, который будет отвечать на GET-запросы:
import express, { Request, Response } from 'express';
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware для парсинга JSON
app.use(express.json());
// Базовый маршрут
app.get('/', (req: Request, res: Response) => {
res.send('REST API на TypeScript работает!');
});
app.listen(PORT, () => {
console.log(`Сервер запущен на http://localhost:${PORT}`);
});
Запустите сервер командой npm run dev и откройте http://localhost:3000. Вы увидите приветственное сообщение.
Создание модели данных
Для полноценного API нам нужна сущность. Создадим простую модель пользователя:
// src/models/user.ts
export interface User {
id: number;
name: string;
email: string;
age: number;
}
export type CreateUserDto = Omit;
Шаг 3: Реализация CRUD-операций
Теперь создадим контроллер и маршруты для работы с пользователями. Создайте файл src/routes/users.ts:
import { Router, Request, Response } from 'express';
import { User, CreateUserDto } from '../models/user';
const router = Router();
let users: User[] = [
{ id: 1, name: 'Иван', email: 'ivan@example.com', age: 28 },
{ id: 2, name: 'Мария', email: 'maria@example.com', age: 32 }
];
let nextId = 3;
// GET /users - получить всех пользователей
router.get('/', (req: Request, res: Response) => {
res.json(users);
});
// GET /users/:id - получить пользователя по ID
router.get('/:id', (req: Request, res: Response) => {
const id = parseInt(req.params.id);
const user = users.find(u => u.id === id);
if (!user) {
return res.status(404).json({ message: 'Пользователь не найден' });
}
res.json(user);
});
// POST /users - создать нового пользователя
router.post('/', (req: Request, res: Response) => {
const { name, email, age }: CreateUserDto = req.body;
if (!name || !email || !age) {
return res.status(400).json({ message: 'Все поля обязательны' });
}
const newUser: User = { id: nextId++, name, email, age };
users.push(newUser);
res.status(201).json(newUser);
});
// PUT /users/:id - обновить пользователя
router.put('/:id', (req: Request, res: Response) => {
const id = parseInt(req.params.id);
const index = users.findIndex(u => u.id === id);
if (index === -1) {
return res.status(404).json({ message: 'Пользователь не найден' });
}
const { name, email, age }: CreateUserDto = req.body;
if (!name || !email || !age) {
return res.status(400).json({ message: 'Все поля обязательны' });
}
users[index] = { id, name, email, age };
res.json(users[index]);
});
// DELETE /users/:id - удалить пользователя
router.delete('/:id', (req: Request, res: Response) => {
const id = parseInt(req.params.id);
const index = users.findIndex(u => u.id === id);
if (index === -1) {
return res.status(404).json({ message: 'Пользователь не найден' });
}
users.splice(index, 1);
res.status(204).send();
});
export default router;
Теперь подключим роутер в главном файле src/index.ts:
import userRoutes from './routes/users';
app.use('/users', userRoutes);
Шаг 4: Middleware для обработки ошибок и логирования
Добавим два полезных middleware: логирование запросов и глобальный обработчик ошибок. Создайте файл src/middleware/errorHandler.ts:
import { Request, Response, NextFunction } from 'express';
export const requestLogger = (req: Request, res: Response, next: NextFunction) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
next();
};
export const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => {
console.error('Ошибка:', err.message);
res.status(500).json({
message: 'Внутренняя ошибка сервера',
error: process.env.NODE_ENV === 'development' ? err.message : undefined
});
};
Подключите middleware в index.ts:
import { requestLogger, errorHandler } from './middleware/errorHandler';
app.use(requestLogger);
app.use('/users', userRoutes);
app.use(errorHandler); // Д