Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке DTO?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)DTO (Data Transfer Object) - об'єкт для передачі даних між шарами застосунку; у NestJS зазвичай це клас, що описує формат вхідних чи вихідних даних (тіла запиту, query-параметрів, відповіді) - визначає, які поля дозволено приймати чи повертати, і їхні типи. **Ключове:** DTO ≠ модель БД - DTO контролює дані на рівні API/контролерів, тоді як entity описує структуру таблиці на рівні ORM; DTO зазвичай анотують декораторами `class-validator` для валідації через `ValidationPipe`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке 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()` | | Інструменти NestJS | `ValidationPipe`, `PartialType`, `OmitType`, `PickType` | | Переваги | Безпека, типізація, валідація, читабельність |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.