Как написать REST API на TypeScript за 30 минут: на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему 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); // Д                

Блоги

Рекомендаций по книгам