Пайпы
Пайп (pipe) — класс, через который проходит аргумент перед тем, как попасть в метод контроллера. Пайп может преобразовать значение (строку "5" в число 5) или проверить его и отклонить запрос с ошибкой 400. ValidationPipe из прошлого урока — тоже пайп.
Встроенный ParseIntPipe
Параметры адреса приходят строками. ParseIntPipe превращает строку в целое число:
// src/posts/posts.controller.ts
import { Controller, Get, Param, ParseIntPipe } from '@nestjs/common';
import { PostsService } from './posts.service';
@Controller('posts')
export class PostsController {
constructor(private readonly postsService: PostsService) {}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return this.postsService.findOne(id);
}
}Пайп передаётся вторым аргументом декоратора. Теперь id — настоящее число, и Number(id) больше не нужен. Откройте /posts/abc — вместо пустого ответа придёт ошибка 400 с текстом Validation failed (numeric string is expected).
Значение по умолчанию
DefaultValuePipe подставляет значение, если параметра нет. Пайпы выполняются слева направо:
// src/posts/posts.controller.ts
import { DefaultValuePipe, Get, ParseIntPipe, Query } from '@nestjs/common';
@Get()
findAll(@Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number) {
return { page };
}/posts вернёт {"page":1}, а /posts?page=3 — {"page":3}.
Встроенные пайпы
| Пайп | Что делает |
|---|---|
ParseIntPipe | Строку в целое число |
ParseFloatPipe | Строку в дробное число |
ParseBoolPipe | "true" и "false" в логическое значение |
ParseUUIDPipe | Проверяет, что строка — UUID |
ParseEnumPipe | Проверяет, что значение из перечисления |
DefaultValuePipe | Подставляет значение по умолчанию |
ValidationPipe | Проверяет объект по правилам DTO |
Свой пайп
Номер страницы не может быть нулём или отрицательным. Создайте пайп:
nest g pipe common/pipes/positive-int --flat// src/common/pipes/positive-int.pipe.ts
import { BadRequestException, Injectable, PipeTransform } from '@nestjs/common';
@Injectable()
export class PositiveIntPipe implements PipeTransform {
transform(value: string): number {
const number = Number(value);
if (!Number.isInteger(number) || number < 1) {
throw new BadRequestException('Ожидается целое число больше нуля');
}
return number;
}
}Пайп реализует интерфейс PipeTransform: метод transform() получает значение и возвращает то, что попадёт в аргумент. Брошенное исключение BadRequestException превращается в ответ 400.
Пайп подключают так же, как встроенные:
// src/posts/posts.controller.ts
import { PositiveIntPipe } from '../common/pipes/positive-int.pipe';
@Get(':id')
findOne(@Param('id', PositiveIntPipe) id: number) {
return this.postsService.findOne(id);
}Адрес /posts/0 вернёт 400 с сообщением «Ожидается целое число больше нуля».
Частая ошибка
Без пайпа тип number у аргумента ничего не меняет: TypeScript не преобразует данные во время работы, и в id по-прежнему лежит строка. Сравнение post.id === id тогда никогда не совпадёт, и сервис вернёт пустой ответ. Если аргумент объявлен числом, к нему нужен ParseIntPipe или transform: true в ValidationPipe.