Що таке DTO?
Що таке DTO
DTO (Data Transfer Object) - це об'єкт для передачі даних між шарами застосунку.
У NestJS під DTO зазвичай розуміють клас, що описує формат вхідних чи вихідних даних (наприклад, тіла запиту body, query-параметрів чи відповіді).
DTO визначає, які поля дозволено приймати й передавати, і їхні типи.
Простий приклад DTO
// create-user.dto.ts
export class CreateUserDto {
name: string;
email: string;
password: string;
}Використання в контролері:
import { Body, Controller, Post } from '@nestjs/common';
import { CreateUserDto } from './create-user.dto';
@Controller('users')
export class UsersController {
@Post()
create(@Body() dto: CreateUserDto) {
// dto: { name, email, password }
return `Створено користувача: ${dto.name}`;
}
}Тепер Nest очікує, що в тілі запиту (body) прийдуть саме ці поля.
Навіщо потрібні DTO
| Причина | Опис |
|---|---|
| Чітка структура даних | Явно описує, які поля приймає API |
| Типізація | Дозволяє IDE й компілятору TypeScript перевіряти типи |
| Безпека | Виключає передачу "зайвих" даних від клієнта |
| Валідація | DTO можна анотувати декораторами (class-validator) |
| Перевикористання | Один DTO можна використовувати в кількох місцях (наприклад, REST і GraphQL) |
DTO ≠ Модель бази даних
Це дуже важлива відмінність:
| DTO | Модель БД |
|---|---|
| Визначає дані, що приходять чи йдуть | Визначає структуру таблиці |
| Використовується на рівні API / контролерів | Використовується в сервісах / ORM |
| Може включати валідацію й обмежені поля | Містить усі стовпці таблиці |
Приклад: CreateUserDto | Приклад: UserEntity (у Prisma чи TypeORM) |
Валідація DTO
Зазвичай DTO використовуються разом з бібліотеками:
class-validator- для перевірки даних;class-transformer- для перетворення plain-об'єктів на екземпляри класів.
Приклад:
import { IsEmail, IsString, MinLength } from 'class-validator';
export class CreateUserDto {
@IsString()
name: string;
@IsEmail()
email: string;
@MinLength(6)
password: string;
}І вмикаємо валідацію в main.ts:
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();Тепер, якщо клієнт надішле:
{
"name": 123,
"email": "wrong",
"password": "123"
}Nest автоматично поверне:
400 Bad Request
[
{ "property": "name", "constraints": { "isString": "name must be a string" } },
{ "property": "email", "constraints": { "isEmail": "email must be an email" } },
{ "property": "password", "constraints": { "minLength": "password must be longer than or equal to 6 characters" } }
]Різні типи DTO
| Назва | Призначення | Приклад |
|---|---|---|
| Create DTO | Для створення сутності | CreateUserDto |
| Update DTO | Для оновлення (частково) | UpdateUserDto |
| Response DTO | Для формату відповіді клієнту | UserResponseDto |
| Query DTO | Для параметрів запиту (?limit=10&page=2) | GetUsersQueryDto |
Приклад Update DTO (часткові поля)
NestJS надає утиліту PartialType() з @nestjs/mapped-types,
щоб на основі одного DTO зробити інший із необов'язковими полями:
import { PartialType } from '@nestjs/mapped-types';
import { CreateUserDto } from './create-user.dto';
export class UpdateUserDto extends PartialType(CreateUserDto) {}Тепер усі поля CreateUserDto стали опціональними - ідеально для PATCH-запитів.
DTO і трансформація даних
Можна застосовувати class-transformer для автоматичного перетворення даних:
import { Transform } from 'class-transformer';
import { IsNumber } from 'class-validator';
export class QueryDto {
@Transform(({ value }) => parseInt(value))
@IsNumber()
limit: number;
}Тепер, якщо прийде ?limit=10, Nest автоматично приведе limit до числа.
Поради щодо DTO
Розділяй DTO за призначенням (Create, Update, Response);
Використовуй class-validator + ValidationPipe;
DTO ≠ Entity, не змішуй шари;
Імпортуй DTO лише в контролери й сервіси;
DTO має бути простим і передбачуваним - без бізнес-логіки.
Підсумок
| Поняття | Опис |
|---|---|
| DTO (Data Transfer Object) | Клас, що описує структуру даних, переданих між шарами |
| Головна мета | Контролювати вхідні/вихідні дані |
| Використовується де | У контролерах (@Body(), @Query(), @Param()) |
| Декоратори | @IsString(), @IsEmail(), @MinLength(), @Transform() |
| Інструменти NestJS | ValidationPipe, PartialType, OmitType, PickType |
| Переваги | Безпека, типізація, валідація, читабельність |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.