Skip to main content

Що таке DTO?

Що таке DTO

DTO (Data Transfer Object) - це об'єкт для передачі даних між шарами застосунку. У NestJS під DTO зазвичай розуміють клас, що описує формат вхідних чи вихідних даних (наприклад, тіла запиту body, query-параметрів чи відповіді).

DTO визначає, які поля дозволено приймати й передавати, і їхні типи.

Простий приклад DTO

javascript
// create-user.dto.ts export class CreateUserDto { name: string; email: string; password: string; }

Використання в контролері:

javascript
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-об'єктів на екземпляри класів.

Приклад:

javascript
import { IsEmail, IsString, MinLength } from 'class-validator'; export class CreateUserDto { @IsString() name: string; @IsEmail() email: string; @MinLength(6) password: string; }

І вмикаємо валідацію в main.ts:

javascript
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();

Тепер, якщо клієнт надішле:

javascript
{ "name": 123, "email": "wrong", "password": "123" }

Nest автоматично поверне:

javascript
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 зробити інший із необов'язковими полями:

javascript
import { PartialType } from '@nestjs/mapped-types'; import { CreateUserDto } from './create-user.dto'; export class UpdateUserDto extends PartialType(CreateUserDto) {}

Тепер усі поля CreateUserDto стали опціональними - ідеально для PATCH-запитів.

DTO і трансформація даних

Можна застосовувати class-transformer для автоматичного перетворення даних:

javascript
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()
Інструменти NestJSValidationPipe, PartialType, OmitType, PickType
ПеревагиБезпека, типізація, валідація, читабельність

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.