npm i class-validator class-transformer @nestjs/mapped-types
Introducción a NestJS
¿Qué es NestJS?
Crea tu primer proyecto con NestJS
Estructura de aplicaciones en NestJS
Presentación del proyecto: Platzi Store
Repaso a TypeScript: tipos y POO
REST API
Introducción a controladores
GET: cómo recibir parámetros
GET: parámetros query
Separación de responsabilidades
Instalación de Postman o Insomnia
Qué es el método POST
Métodos PUT y DELETE para editar y eliminar
Códigos de estado o HTTP response status codes
Integridad de datos
Introducción a servicios: crea tu primer servicio
Implementando servicios en tu controlador
Manejo de errores con throw y NotFoundException
Introducción a pipes: usa tu primer pipe
Crea tu propio pipe
Creando Data Transfers Objects
Validando parámetros con class-validator y mapped-types
Cómo evitar parámetros incorrectos
Próximos pasos
Reto: controladores y servicios restantes
Continúa con el Curso de NestJS: Programación Modular
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Los DTO no solo sirven para tipar y determinar la estructura de los datos de entrada de un endpoint, también pueden contribuir en la validación de los datos y en la entrega de mensajes al front-end en caso de error en los mismos.
Utiliza el comando npm i class-validator class-transformer
para instalar dos dependencias que nos ayudarán en la validación de los datos.
Estas librerías traen un set de decoradores para las propiedades de los DTO y así validar los tipos de datos de entrada.
import { IsNotEmpty, IsString, IsNumber, IsUrl } from 'class-validator';
export class CreateProductDTO {
@IsNotEmpty()
@IsString()
readonly name: string;
@IsNotEmpty()
@IsString()
readonly description: string;
@IsNotEmpty()
@IsNumber()
readonly price: number;
@IsNotEmpty()
@IsUrl()
readonly image: string;
}
Estas validaciones contribuyen en la experiencia de desarrollo devolviendo mensajes al front-end sobre qué datos están faltando o cuáles no son correctos. Por ejemplo, si en el Body de la petición enviamos.
{
"name": "Nombre producto",
"price": 100,
"image": "imagen"
}
El servidor nos devolverá el siguiente mensaje:
{
"statusCode": 400,
"message": [
"description should not be empty",
"description must be a string",
"image must be an URL address"
],
"error": "Bad Request"
}
Indicando que la solicitud espera de forma obligatoria un campo description
del tipo string y un campo image
con una URL.
A medida que tu aplicación crezca, tendrás que crear muchos DTO, para la creación de un producto, edición, filtros, etc. Una buena práctica es la reutilización de las clases DTO que ya tengas implementado para no repetir propiedades.
Instala la dependencia @nestjs/mapped-types
que nos ayudará con la reutilización de código de la siguiente manera.
import { IsNotEmpty, IsString, IsNumber, IsUrl } from 'class-validator';
import { PartialType, OmitType } from '@nestjs/mapped-types';
export class CreateProductDTO {
@IsNotEmpty()
@IsString()
readonly name: string;
@IsNotEmpty()
@IsString()
readonly description: string;
@IsNotEmpty()
@IsNumber()
readonly price: number;
@IsNotEmpty()
@IsUrl()
readonly image: string;
}
export class UpdateProductDto extends PartialType(
OmitType(CreateProductDTO, ['name']),
) {}
Importa PartialType y OmitType desde @nestjs/mapped-types
.
PartialType permite extender una clase de otra y que todos sus campos sean opcionales. Así, el DTO UpdateProductDto no tiene como obligatorio sus campos y es posible editar todos o solo uno.
Por otro lado, OmitType, permite la omisión de campos haciendo que cierta cantidad de ellos no formen parte del DTO en el caso de que dichos campos no deban ser editados.
npm i class-validator class-transformer @nestjs/mapped-types
// src/dtos/products.dtos.ts
import {
IsString,
IsNumber,
IsUrl,
IsNotEmpty,
IsPositive,
} from 'class-validator';
import { PartialType } from '@nestjs/mapped-types';
export class CreateProductDto {
@IsString()
@IsNotEmpty()
readonly name: string;
@IsString()
@IsNotEmpty()
readonly description: string;
@IsNumber()
@IsNotEmpty()
@IsPositive()
readonly price: number;
@IsNumber()
@IsNotEmpty()
@IsPositive()
readonly stock: number;
@IsUrl()
@IsNotEmpty()
readonly image: string;
}
export class UpdateProductDto extends PartialType(CreateProductDto) {}
// src/main.ts
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
...
app.useGlobalPipes(new ValidationPipe());
...
}
bootstrap();
Contribución creada por: Kevin Fiorentino.
Aportes 33
Preguntas 23
npm i class-validator class-transformer @nestjs/mapped-types
Tremendo aporte de los validadores. Es increíble todo lo que nos brinda Nest.js.
Con class-validator también tenemos la opción de retornar mensajes personalizados para cada una de las validaciones.
Solo basta con, en la validación que corresponda, agregar un objeto con la key message que contendra dicho mensaje.
Y la respuesta de la API se verá algo así:
Validar que los tipos coincidan con los DTOs
Instalar dependencias: npm install @nestjs/mapped-types class-validator class-transformer
Importar las dependencias en el main.ts
import { NestFactory } from '@nestjs/core';
import { ValidationPipe } from '@nestjs/common';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
bootstrap();
importar en el DTO:
import {
IsString,
IsNumber,
IsUrl,
IsNotEmpty,
IsPositive,
} from 'class-validator';
import { PartialType } from '@nestjs/mapped-types';
Implementar en la clase del DTO:
export class CreateProductDto {
@IsString()
@IsNotEmpty()
readonly name: string;
@IsString()
@IsNotEmpty()
readonly description: string;
@IsNumber()
@IsNotEmpty()
@IsPositive()
readonly price: number;
@IsNumber()
@IsNotEmpty()
@IsPositive()
readonly stock: number;
@IsUrl() //valida que sea una url
@IsNotEmpty()
readonly image: string;
}
Se puede extender a una clase pero que sea opcional pero que valida sus campos de esta forma:
export class UpdateProductDto extends PartialType(CreateProductDto) {}
Se puede extender un mensaje custom al decorador
@IsString({message: 'My custom message'})
Wow no conocía estas opciones de nest, y al principio parece too much, para una api bien robusta me parece perfecto.
Al querer instalar @nestjs/mapped-types me encontre con problemas de dependencias internas con class-transformer.
En este momento (noviembre 2021) class-transformer esta en version 0.5.1 y @nestjs/mapped-types requiere 0.4.0.
Solucion instalar: npm i [email protected] y luego npm i @nestjs/mapped-types
Si quieren agregar un campo en el DTO con tipo Date
pueden hacer esto:
main.ts
app.useGlobalPipes(new ValidationPipe({ transform: true }));
@Type
de la libreria class-transform
@IsDate()
@Type(() => Date)
@IsNotEmpty()
readonly date: Date;
"date": "06/18/2021",
Ok estas validaciones son middleware, creería yo…
nest es BRUTAL
Para quienes estén haciendo el curso y tengan un error al instalar mapped-types deben usar la versión 0.13.0 de class-validator, hasta ahora no es compatible con la versión 0.14.0 que es la que se instala por defecto
npm i [email protected]
Hola 👋
Para los que preferimos yarn
sobre npm
yarn add class-validator class-transformer
Espero haberles aportado algo 🚀
Importante
Recuerden poner el nombre de las importaciones de class-validator
en CammelCase, o sea, con la primera letra en mayuscula, ya que tambien tienen su opcion de ponerlo en minuscula pero en esa le tienes que pasar el valor dentro de los parentesis.
Instalar una dependencia de @nestjs mapped-types nos ayuda a reutilizar código de clases que ya tenemos
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe());
await app.listen(3000);
}
Al día de hoy a mi no me funciono el comando
npm i @nestjs/mapped-types
Ya que según la documentación de nest ahora dice que debemos usar @nestjs/swagger
npm i @nestjs/swagger
y para que realmente sea opcional debemos agregar el decorador @ApiProperty()
para que PartialType los pueda omitir quedando de la siguiente manera
export class CreateProductDto {
@IsNotEmpty()
@IsString()
@ApiProperty()
readonly name: string;
@IsNotEmpty()
@IsString()
@ApiProperty()
readonly description: string;
@IsNotEmpty()
@IsNumber()
@IsPositive()
@ApiProperty()
readonly stock: number;
@IsNotEmpty()
@IsUrl()
@ApiProperty()
readonly image: string;
@IsNotEmpty()
@IsNumber()
@IsPositive()
@ApiProperty()
readonly price: number;
}
Fuente: https://docs.nestjs.com/openapi/mapped-types#mapped-types
Me encontré la documentación de Nest sobre este tema acá
Que maravilloso.
el cero no lo válida como positivo
Es increible la cantidad de tiempo que nos ahorran los decoradores de validación. Aunque solo es un layer más ya que la robustez de los datos debe siempre estar en los modelos. Excelente clase!
uff que hit este tema
Add @nestjs/mapped-types
Using Class validator annotations for execution time validation not only dev experience
Add class-validator and class-transformer
Bonito aporte!
Al venir de express, me faltó gritar de alegría al ver estos decoradores!!! es increible la cantidad de trabajo que nos ahorran.
Normalmente cuando hago apis las hago con express + typescript, y este tipo de validaciones las hago con express-validators, y es un poco engorroso crear middlewares para responder el error. Crear dtos es mucho más sencillo.
Utilizar decorador @isPositive para numeros positivos de class-validator
Activar las validaciones de class-validator
class-validator tienes muchos decoradores uno de ellos son: @isString, @isNumber,@isUrl, @isEmail, @isNotEmpity
instalar la dependencia class-validator y la class-transformer
Encantado con esta parte de la validación, sobre todo el uso de Dtos, que es de gran apoyo.
PartialType
👏👏
Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.