NestJS для TypeScript: полное руководство с примерами

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

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

Начать курс

Введение в NestJS

NestJS (Nest) — это прогрессивный фреймворк для создания эффективных, масштабируемых и надежных серверных приложений на Node.js. Он использует TypeScript в качестве основного языка и вдохновлен архитектурой Angular. NestJS предоставляет готовую архитектуру приложения, которая помогает разработчикам создавать хорошо структурированный, тестируемый и поддерживаемый код.

Основная цель NestJS — решить проблему отсутствия четкой архитектуры в экосистеме Node.js. В отличие от Express или Fastify, которые являются минималистичными и не навязывают структуру, NestJS предлагает готовые абстракции: модули, контроллеры, сервисы, провайдеры и middleware. Это особенно полезно для крупных корпоративных проектов, где важна предсказуемость и стандартизация кода.

NestJS построен поверх HTTP-фреймворков (по умолчанию Express, но можно использовать Fastify) и добавляет к ним мощную систему внедрения зависимостей (Dependency Injection), декораторы, Guards, Interceptors, Pipes и Filters. Фреймворк активно использует декораторы TypeScript, что делает код декларативным и читаемым.

Установка NestJS

Для установки NestJS вам потребуется Node.js (версия 16 или выше) и менеджер пакетов npm (или yarn, pnpm).

Самый простой способ начать — использовать Nest CLI:

npm install -g @nestjs/cli
nest new my-nest-project
cd my-nest-project
npm run start:dev

Если вы предпочитаете установить NestJS в уже существующий проект:

npm install @nestjs/core @nestjs/common @nestjs/platform-express reflect-metadata rxjs typescript @types/node

Также потребуется установить TypeScript и ts-node для разработки:

npm install -D typescript @types/node ts-node

Важно: NestJS использует библиотеку reflect-metadata для работы с декораторами. Убедитесь, что она импортирована в главном файле main.ts:

import "reflect-metadata";

Быстрый старт с примером кода

Создадим простое REST API приложение с одним эндпоинтом, который возвращает приветствие.

Структура проекта:

src/
├── app.controller.ts
├── app.module.ts
├── app.service.ts
└── main.ts

main.ts — точка входа:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
  console.log('Server is running on http://localhost:3000');
}
bootstrap();

app.module.ts — корневой модуль:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

app.controller.ts — контроллер:

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

app.service.ts — сервис (бизнес-логика):

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World!';
  }
}

Запустите приложение командой npm run start:dev и откройте http://localhost:3000. Вы увидите "Hello World!".

Основные методы и функции NestJS

Рассмотрим 10 ключевых элементов NestJS, которые используются в каждом проекте.

1. @Module() — декоратор модуля

Что делает: Определяет класс как модуль NestJS. Модуль — это контейнер для контроллеров, сервисов и других модулей. Он организует приложение в логические блоки.

Параметры:

  • imports — массив импортируемых модулей
  • controllers — массив контроллеров, принадлежащих модулю
  • providers — массив сервисов/провайдеров
  • exports — массив провайдеров, которые будут доступны другим модулям

Пример:

import { Module } from '@nestjs/common';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { DatabaseModule } from '../database/database.module';

@Module({
  imports: [DatabaseModule],
  controllers: [UsersController],
  providers: [UsersService],
  exports: [UsersService],
})
export class UsersModule {}

2. @Controller() — декоратор контроллера

Что делает: Определяет класс как контроллер, который обрабатывает входящие HTTP-запросы. Можно указать префикс маршрута.

Параметры: prefix (строка) — префикс для всех маршрутов в контроллере.

Пример:

import { Controller, Get } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get()
  findAll(): string {
    return 'This action returns all users';
  }
}
// Маршрут: GET /users

3. @Injectable() — декоратор сервиса

Что делает: Помечает класс как провайдер, который может быть внедрен через Dependency Injection. Обычно используется для сервисов, репозиториев, фабрик.

Параметры: Нет обязательных параметров.

Пример:

import { Injectable } from '@nestjs/common';

@Injectable()
export class UsersService {
  private readonly users = [];

  findAll() {
    return this.users;
  }

  create(user) {
    this.users.push(user);
  }
}

4. @Get(), @Post(), @Put(), @Delete() — декораторы HTTP методов

Что делает: Привязывают метод контроллера к конкретному HTTP-методу и пути. Позволяют создавать RESTful эндпоинты.

Параметры: path (строка, опционально) — дополнительный путь к маршруту.

Пример:

import { Controller, Get, Post, Body, Param } from '@nestjs/common';

@Controller('users')
export class UsersController {
  @Get()
  findAll(): string { return 'GET all users'; }

  @Get(':id')
  findOne(@Param('id') id: string): string {
    return `GET user with id ${id}`;
  }

  @Post()
  create(@Body() createUserDto: any): string {
    return `POST create user: ${JSON.stringify(createUserDto)}`;
  }
}

5. @Param() — декоратор параметра маршрута

Что делает: Извлекает параметры из URL (например, /users/:id). Позволяет получить доступ к динамическим сегментам пути.

Параметры: property (строка, опционально) — имя параметра. Если не указан, возвращает весь объект params.

Пример:

@Get(':id')
findOne(@Param('id') id: string): string {
  return `User ID: ${id}`;
}

@Get(':id/:name')
findByName(@Param() params: any): string {
  return `ID: ${params.id}, Name: ${params.name}`;
}

6. @Body() — декоратор тела запроса

Что делает: Извлекает тело POST/PUT/PATCH запроса. Обычно используется вместе с DTO (Data Transfer Object) для валидации.

Параметры: Нет обязательных параметров.

Пример:

import { IsString, IsInt } from 'class-validator';

export class CreateUserDto {
  @IsString()
  name: string;

  @IsInt()
  age: number;
}

@Post()
create(@Body() createUserDto: CreateUserDto): string {
  return `User created: ${createUserDto.name}, ${createUserDto.age}`;
}

7. @Query() — декоратор query-параметров

Что делает: Извлекает параметры из строки запроса (query string), например /users?page=1&limit=10.

Параметры: property (строка, опционально) — имя параметра.

Пример:

@Get()
findAll(@Query('page') page: number = 1, @Query('limit') limit: number = 10): string {
  return `Page: ${page}, Limit: ${limit}`;
}

@Get('search')
search(@Query() query: any): string {
  return `Search query: ${JSON.stringify(query)}`;
}

8. @UsePipes() — декоратор пайпов (валидация и трансформация)

Что делает: Применяет пайпы к контроллеру или методу. Пайпы используются для валидации входных данных и их трансформации. NestJS имеет встроенные пайпы, такие как ValidationPipe, ParseIntPipe, ParseUUIDPipe.

Параметры: Один или несколько экземпляров пайпов.

Пример:

import { Controller, Get, Param, ParseIntPipe, UsePipes, ValidationPipe } from '@nestjs/common';

@Controller('users')
@UsePipes(new ValidationPipe()) // Применяем глобально к контроллеру
export class UsersController {
  @Get(':id')
  findOne(@Param('id', ParseIntPipe) id: number): string {
    return `User ID (number): ${id}`;
  }
}

9. @UseGuards() — декоратор гардов (авторизация)

Что делает: Применяет гарды к контроллеру или методу. Гарды определяют, может ли запрос быть обработан (например, проверка JWT токена, роли пользователя).

Параметры: Один или несколько классов гардов.

Пример:

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
    const request = context.switchToHttp().getRequest();
    return request.headers.authorization === 'Bearer secret-token';
  }
}

@Controller('admin')
@UseGuards(AuthGuard)
export class AdminController {
  @Get()
  getAdminData(): string {
    return 'Admin data';
  }
}

10. @Catch() и Exception Filters — фильтры исключений

Что делает: Перехватывает исключения и преобразует их в понятный HTTP-ответ. Позволяет централизованно обрабатывать ошибки.

Параметры: Массив типов исключений для перехвата.

Пример:

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Response } from 'express';

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse<Response>();
    const status = exception.getStatus();
    const message = exception.message;

    response.status(status).json({
      statusCode: status,
      timestamp: new Date().toISOString(),
      message: message,
    });
  }
}

// Использование в контроллере:
@Controller('users')
@UseFilters(new HttpExceptionFilter())
export class UsersController {
  @Get(':id')
  findOne(@Param('id') id: string): string {
    throw new HttpException('User not found', 404);
  }
}

Реальный практический пример использования

Создадим полноценный CRUD для управления задачами (Todo list) с использованием TypeORM для работы с базой данных SQLite.

Шаг 1: Установка зависимостей

<

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