No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Compra acceso a todo Platzi por 1 a帽o

Antes: $249

Currency
$209/a帽o

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscr铆bete

Termina en:

16D
6H
47M
52S

Validando par谩metros con class-validator y mapped-types

20/23
Recursos

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.

Validaci贸n de datos con DTO

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.

C贸mo reutilizar c贸digo de los DTO

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.

Instalar 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 35

Preguntas 24

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

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铆:

npm i class-validator class-transformer @nestjs/mapped-types

Tremendo aporte de los validadores. Es incre铆ble todo lo que nos brinda Nest.js.

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'})

Si quieren agregar un campo en el DTO con tipo Date pueden hacer esto:

  1. Permiten la transformacion en el main.ts
  app.useGlobalPipes(new ValidationPipe({ transform: true }));
  1. Agregan @Type de la libreria class-transform
@IsDate()
@Type(() => Date)
@IsNotEmpty()
readonly date: Date;
  1. En el request pueden enviar varios formatos, por ej:
    "date": "06/18/2021",

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

Ok estas validaciones son middleware, creer铆a yo鈥

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

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]

nest es BRUTAL

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.

uff que hit este tema

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.

Se puede implementar el uso de utility types de typescript para los dtos.
Para el caso del m茅todo PUT se podr铆a usar Partial, sin tener que generar una clase nueva 煤nicamente para ese m茅todo.

export class ProductDto {
  @IsString()
  @IsNotEmpty()
  readonly name: string;

  @IsString()
  @IsNotEmpty()
  readonly description: string;

  @IsNumber()
  @IsNotEmpty()
  readonly price: number;

  @IsNumber()
  @IsNotEmpty()
  readonly stock: number;

  @IsUrl()
  @IsNotEmpty()
  readonly image: string;
}

  • Controlador @Put:
  @Put(':id')
  update(
      @Param('id', ParseIntPipe) id: number, 
      @Body()  payload: Partial<ProductDto>) {
      return this._productService.update(id, payload); 
   }
  • Service
  update(id: number, payload: Partial<ProductDto>) {}

Hola 馃憢
Para los que preferimos yarn sobre npm

yarn add class-validator class-transformer

Espero haberles aportado algo 馃殌

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);
}
uno podria marcar a una clase con un me gusta por ejemplo esta, esta buenisima la validacion de Typos como lo hace NestJS

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!

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.

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

馃憦馃憦