Qué son los decoradores de validación en NestJS y cómo usarlos


Aprende qué son los decoradores de validación en NestJS, cómo usar class-validator y ValidationPipe con ejemplos claros y prácticos

oscar Escrito por oscar 22 October 2025 28 0

En NestJS, validar correctamente los datos de entrada es clave para construir APIs seguras y mantenibles. En este artículo aprenderás qué son los decoradores de validación en NestJS, cómo funcionan junto a ValidationPipe y cómo usarlos en DTOs con ejemplos reales usando class-validator.

¿Qué son los decoradores de validación de NestJS?

En NestJS, los decoradores de validación son anotaciones que se aplican a las clases DTO (Data Transfer Objects) para definir reglas de validación de los datos de entrada (por ejemplo, el body de una petición HTTP).

Se basan principalmente en dos librerías:

NestJS las integra mediante el ValidationPipe.

¿Para qué sirven?

Permiten:

Flujo general de validación en NestJS

El cliente envía una petición (ej. POST con JSON)

  1. NestJS convierte el payload a un DTO
  2. Se ejecutan los decoradores de validación
  3. Si hay errores → NestJS responde con 400 Bad Request
  4. Si todo es válido → el controlador recibe el DTO tipado

Instalación necesaria

npm install class-validator class-transformer

Habilitar validaciones (ValidationPipe)

Global (recomendado)

// main.ts
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true,
    forbidNonWhitelisted: true,
    transform: true,
  }),
);

¿Qué hace cada opción?

Ejemplo completo NestJS

En una clase Dto

import { IsString, IsInt, Min, IsOptional, IsEmail, Length } from 'class-validator';

export class CreateUserDto {
  @IsString()
  @Length(3, 50)
  nombre: string;

  @IsInt()
  @Min(18)
  edad: number;

  @IsEmail()
  email: string;

  @IsOptional()
  @IsString()
  nickname?: string;
}

Uso en un controlador

@Post()
create(@Body() createUserDto: CreateUserDto) {
  return createUserDto;
}

Decoradores de validación

Tipos básicos

Decorador Descripción Ejemplo de uso ✅ Válido ❌ Inválido
@IsString() Debe ser una cadena name: "Juan" "Hola" 123
@IsBoolean() Debe ser true o false activo: true true "true"
@IsNumber() Debe ser numérico precio: 99.5 42 "42"
@IsInt() Entero solamente edad: 25 25 25.5
@IsDecimal() Decimal válido tasa: "12.50" "12.50" "abc"
@IsArray() Arreglo válido tags: ["a", "b"] ["x", "y"] "no array"
@IsObject() Objeto plano data: {a: 1} {name: "x"} null
@IsEnum(Rol) Dentro de un enum Rol.ADMIN "ADMIN" "SUPERADMIN"
@IsDate() Objeto Date new Date() new Date("2025-10-22") "2025-10-22"
@IsDateString() Fecha en formato ISO "2025-10-22T10:00:00Z" "2025-05-15T00:00:00Z" "15/05/2025"
@IsUUID() UUID válido "550e8400-e29b-41d4-a716-446655440000" "550e8400-e29b-41d4-a716-446655440000" "12345"

Validaciones numéricas

Decorador Descripción Ejemplo ✅ Válido ❌ Inválido
@Min(10) Mínimo permitido edad: 15 15 5
@Max(100) Máximo permitido puntuacion: 80 80 120
@IsPositive() Mayor que 0 monto: 5 5 -1
@IsNegative() Menor que 0 saldo: -10 -10 5
@IsDivisibleBy(5) Múltiplo de 5 valor: 10 10 12

Cadenas de texto

Decorador Descripción Ejemplo ✅ Válido ❌ Inválido
@Length(3, 10) Entre 3 y 10 caracteres "Oscar" "Oscar" "O"
@MinLength(5) Longitud mínima "HolaMundo" "ABCDE" "Hi"
@MaxLength(8) Longitud máxima "Usuario" "Admin" "Administrador"
@IsNotEmpty() No vacío "valor" "texto" ""
@IsEmpty() Debe estar vacío "" "" "algo"
@Matches(/^[A-Z]+$/) Cumple regex "ABC" "HELLO" "Hello"
@Contains("abc") Contiene substring "zabcx" "123abc" "xyz"
@NotContains("admin") No debe contener "user123" "user123" "adminUser"
@StartsWith("pre") Empieza con "prefix" "preload" "loadpre"
@EndsWith("end") Termina con "theend" "weekend" "endless"
@IsIn(["A", "B", "C"]) Dentro del conjunto "B" "A" "Z"
@IsNotIn(["X", "Y"]) No dentro del conjunto "A" "A" "X"

Formatos específicos

Decorador Descripción Ejemplo ✅ Válido ❌ Inválido
@IsEmail() Email válido "a@b.com" "test@gmail.com" "correo@"
@IsUrl() URL válida "https://openai.com" "https://google.com" "www.google"
@IsPhoneNumber('ES') Teléfono España "+34611222333" "+34622333444" "611222333"
@IsIP('4') IP v4 "192.168.1.1" "10.0.0.1" "999.999.1.1"
@IsPort() Puerto TCP 8080 3000 70000
@IsFQDN() Dominio completo "example.com" "google.com" "localhost"
@IsBase64() Cadena Base64 "U29tZVRleHQ=" "SGVsbG8=" "Hola"
@IsHexColor() Color #hex "#AABBCC" "#ff0000" "red"
@IsRgbColor() Color RGB válido "rgb(255,0,0)" "rgb(0,128,255)" "rgba(0,0,0)"
@IsLatitude() Latitud válida 40.4168 -23.55 120.0
@IsLongitude() Longitud válida -3.7038 -74.06 190.1
@IsTimeZone() Zona horaria "Europe/Madrid" "America/Bogota" "Mars/Colony1"

Validaciones de arreglos

Decorador Descripción Ejemplo ✅ Válido ❌ Inválido
@ArrayContains(['a']) Contiene los valores ["a","b"] ["a","x"] ["x"]
@ArrayNotContains(['z']) No contiene ["a","b"] ["x","y"] ["a","z"]
@ArrayMinSize(2) Mínimo tamaño ["a","b"] ["x","y"] ["a"]
@ArrayMaxSize(3) Máximo tamaño ["a","b"] ["1","2","3"] ["1","2","3","4"]
@ArrayUnique() Todos únicos ["a","b"] ["1","2","3"] ["a","a"]

Otros validadores útiles

Decorador Descripción Ejemplo ✅ Válido ❌ Inválido
@IsDefined() No puede ser undefined "valor" "dato" undefined
@IsOptional() Se omite si falta null o omitido undefined (ignorado)
@ValidateNested() Valida objeto hijo user: UserDto { user: {...} } { user: "texto" }
@Type(() => Clase) Transforma tipo (de class-transformer) @Type(() => User) ✅ — ❌ —
@ValidateIf(o => o.edad > 18) Solo si condición cumple Valida cuando edad > 18 Ignorado si no

Comentario

Debe aceptar antes de enviar