47. DTO - Data Transfer Object
DTO (Data Transfer Object) en NestJS: Validando Datos Antes de Llegar a la Base de Datos
En el desarrollo de APIs con NestJS, una de las mejores prácticas para manejar y validar datos es el uso de DTOs (Data Transfer Objects). Estos objetos nos permiten definir la estructura de los datos que fluyen entre diferentes partes de nuestra aplicación, asegurando consistencia y validación antes de que la información llegue a la base de datos.
¿Qué es un DTO?
Un DTO (Data Transfer Object) es un patrón de diseño que representa cómo se transfieren los datos entre diferentes capas de la aplicación. En NestJS, generalmente se implementa como una clase TypeScript que define la estructura esperada de los datos.
Ventajas de usar DTOs:
✅ Validación de datos: Asegura que los datos cumplan con un formato específico.
✅ Documentación implícita: La estructura del DTO sirve como documentación de los campos esperados.
✅ Seguridad: Evita que se envíen propiedades no deseadas.
✅ Mantenibilidad: Facilita cambios futuros en la estructura de los datos.
Ejemplo Práctico: DTO para Crear un Automóvil
Estructura del Proyecto
src/
│
├── cars/
│ ├── dto/
│ │ ├── create-car.dto.ts
│ │ └── update-car.dto.ts
│ ├── interfaces/
│ │ └── car.interface.ts
│ ├── cars.controller.ts
│ ├── cars.module.ts
│ ├── cars.service.ts
│ └── constants/
│ └── car.constants.ts
│
├── common/
│ ├── pipes/
│ │ └── validation.pipe.ts
│ └── filters/
│ └── http-exception.filter.ts
│
├── app.module.ts
├── app.controller.ts
├── app.service.ts
└── main.ts1. Creando el DTO (create-car.dto.ts)
Definimos la estructura esperada para crear un automóvil:
export class CreateCarDto {
readonly brand: string;
readonly model: string;
}Usamos
readonlypara evitar modificaciones accidentales.Solo aceptamos
brandymodel(ningún otro campo será válido).
Comparación: Controlador SIN DTO vs CON DTO
1. Versión SIN DTO (Problemas de estructura)
import { Controller, Post, Body } from '@nestjs/common';
@Controller('cars')
export class CarsController {
@Post()
createCar(@Body() body: any) { // ❌ 'any' permite cualquier dato
return body;
}
}
Problemas:
No hay validación de estructura.
Cualquier campo puede llegar (incluso mal escritos como Brand en vez de brand).
Riesgo de errores al interactuar con la base de datos.
import { Controller, Post, Body } from '@nestjs/common'; @Controller('cars') export class CarsController { @Post() createCar(@Body() body: any) { // ❌ 'any' permite cualquier dato return body; } }
No hay validación de estructura.
Cualquier campo puede llegar (incluso mal escritos como Brand en vez de brand).
Riesgo de errores al interactuar con la base de datos.
2. Actualizando el Controlador (cars.controller.ts)
Modificamos el método POST para usar el DTO:
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateCarDto } from './dto/create-car.dto';
@Controller('cars')
export class CarsController {
@Post()
createCar(@Body() createCarDto: CreateCarDto) {
return createCarDto;
}
}Ahora,
@Body()espera un objeto que cumpla con la estructura deCreateCarDto.
3. Problema Actual: Falta Validación
Si probamos en Postman, aún podemos enviar datos incorrectos:
{
"Brand": "Toyota", // ❌ Mayúscula incorrecta
"Model": "Corolla", // ❌ Mayúscula incorrecta
"extraField": 123 // ❌ Campo no permitido
}Solución: Necesitamos validar los datos antes de procesarlos.
Próximos Pasos: Validación con Class Validator
En el siguiente post, veremos cómo integrar class-validator y class-transformer para:
✔ Validar que los campos sean correctos.
✔ Rechazar campos no definidos en el DTO.
✔ Mostrar mensajes de error claros.
Conclusión
Los DTOs son esenciales para mantener una API robusta y bien estructurada. Nos ayudan a:
🔹 Definir la estructura de datos esperada.
🔹 Evitar errores en la base de datos.
🔹 Mejorar la legibilidad del código.
En el próximo tutorial, implementaremos validaciones automáticas para garantizar que los datos sean correctos antes de procesarlos.
🚀 ¿Te gustaría aprender más sobre validación en NestJS? ¡Déjalo en los comentarios!
Comentarios
Publicar un comentario