Suggest an editImprove this articleRefine the answer for “What is a DTO?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)A DTO (Data Transfer Object) is an object used to move data between layers of an application; in NestJS it's typically a class that describes the shape of input or output data (a request body, query params, a response) - defining which fields are allowed and their types. **Key point:** a DTO isn't the same as a DB model - a DTO controls data at the API/controller level, while an entity describes a table's structure at the ORM level; DTOs are usually annotated with `class-validator` decorators for validation via `ValidationPipe`.Shown above the full answer for quick recall.Answer (EN)Image## What a DTO is A **DTO (Data Transfer Object)** is an **object used to move data** between an application's layers. In NestJS, a DTO is usually a **class** describing the **shape of input or output data** (e.g. a request `body`, query parameters, or a response). > A DTO defines **which fields are allowed in and out**, and their types. ## A simple DTO example ```javascript // create-user.dto.ts export class CreateUserDto { name: string; email: string; password: string; } ``` Using it in a controller: ```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 `Created user: ${dto.name}`; } } ``` Now Nest expects exactly these fields to arrive in the request body. ## Why DTOs are needed | Reason | Description | |---|---| | A clear data structure | Explicitly states which fields the API accepts | | Typing | Lets the IDE and the TypeScript compiler check types | | Security | Prevents "extra" data from the client getting through | | Validation | A DTO can be annotated with decorators (`class-validator`) | | Reuse | The same DTO can be used in several places (e.g. REST and GraphQL) | ## DTO ≠ a database model This is a very important distinction: | DTO | DB model | |---|---| | Defines **the data coming in or going out** | Defines **a table's structure** | | Used at the **API/controller level** | Used in **services/the ORM** | | Can include **validation** and **restricted fields** | Contains every column of the table | | Example: `CreateUserDto` | Example: `UserEntity` (in Prisma or TypeORM) | ## Validating a DTO DTOs are usually used together with: - `class-validator`, for checking the data; - `class-transformer`, for converting plain objects into class instances. Example: ```javascript import { IsEmail, IsString, MinLength } from 'class-validator'; export class CreateUserDto { @IsString() name: string; @IsEmail() email: string; @MinLength(6) password: string; } ``` And enabling validation in `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(); ``` Now if a client sends: ```javascript { "name": 123, "email": "wrong", "password": "123" } ``` Nest automatically returns: ```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" } } ] ``` ## Different kinds of DTO | Name | Purpose | Example | |---|---|---| | Create DTO | For creating an entity | `CreateUserDto` | | Update DTO | For (partial) updates | `UpdateUserDto` | | Response DTO | For the response format sent to the client | `UserResponseDto` | | Query DTO | For request parameters (`?limit=10&page=2`) | `GetUsersQueryDto` | ## An Update DTO example (partial fields) NestJS provides a `PartialType()` utility from `@nestjs/mapped-types` to derive one DTO with optional fields from another: ```javascript import { PartialType } from '@nestjs/mapped-types'; import { CreateUserDto } from './create-user.dto'; export class UpdateUserDto extends PartialType(CreateUserDto) {} ``` Now every field of `CreateUserDto` becomes **optional**, perfect for PATCH requests. ## DTOs and data transformation `class-transformer` can be applied to automatically convert data: ```javascript import { Transform } from 'class-transformer'; import { IsNumber } from 'class-validator'; export class QueryDto { @Transform(({ value }) => parseInt(value)) @IsNumber() limit: number; } ``` Now if `?limit=10` comes in, Nest automatically converts `limit` to a number. ## Tips for DTOs Split DTOs by purpose (`Create`, `Update`, `Response`); Use `class-validator` + `ValidationPipe`; DTO ≠ Entity, don't mix the layers; Import a DTO **only into controllers and services**; A DTO should be **simple and predictable**, with no business logic. ## Summary | Concept | Description | |---|---| | DTO (Data Transfer Object) | A class describing the shape of data passed between layers | | Main goal | Controlling the input/output data | | Used in | Controllers (`@Body()`, `@Query()`, `@Param()`) | | Decorators | `@IsString()`, `@IsEmail()`, `@MinLength()`, `@Transform()` | | NestJS tools | `ValidationPipe`, `PartialType`, `OmitType`, `PickType` | | Advantages | Security, typing, validation, readability |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.