Performance: Why DTOs enforce data contracts
This concept affects the speed and reliability of data validation and transformation during API request handling, impacting server response time and error handling.
import { IsString, IsEmail } from 'class-validator'; export class CreateUserDto { @IsString() name: string; @IsEmail() email: string; } async createUser(data: CreateUserDto) { // Data validated and structured by DTO const user = await this.userService.create(data); return user; }
async createUser(data: any) { // No validation or structure enforcement const user = await this.userService.create(data); return user; }
| Pattern | Validation Overhead | Error Handling Cost | Response Time Impact | Verdict |
|---|---|---|---|---|
| No DTOs, untyped data | None upfront | High due to runtime errors | Slower due to retries | [X] Bad |
| DTOs with validation decorators | Moderate upfront | Low due to early rejection | Faster and stable | [OK] Good |
email property?class RegisterDto {
username: string;
email: string;
}
@Post('register')
register(@Body() data: RegisterDto) {
return data;
}email is missingemail, validation fails and the request is rejected. If no validation, email would be undefined, but NestJS commonly uses validation pipes.class UpdateProfileDto {
name?: string;
age?: number;
}
@Post('update')
update(@Body() data: UpdateProfileDto) {
return data;
}password field is always a string with at least 8 characters. Which approach best enforces this contract in NestJS?@IsString() and @MinLength(8) on the password property uses decorators to enforce string type and minimum length. Manually check the password length inside the controller method requires manual checks, which is less clean. Define password: string in the DTO without decorators lacks validation. Use a plain JavaScript object instead of a class for the DTO loses type safety and validation.Pass the test and this pattern moves unknown