How to Validate Data in NestJS

Updated: December 31, 2023 By: Guest Contributor Post a comment

Overview

NestJS employs decorators and class-transformer packages to create robust data validation systems. This guide introduces approaches for validating data at various layers in a NestJS application.

Data validation is a critical aspect of building secure and robust web applications. In NestJS, a Node.js framework with TypeScript support, validation can be implemented efficiently with the help of class-validator and class-transformer libraries. These libraries are utilized in tandem to enforce validation rules and transform request payloads into typed objects.

Setting up the Validation Pipeline with DTOs

The first step towards implementing validation in NestJS is to set up Data Transfer Objects (DTOs) with decorators that define the validation rules. Install the required packages with:

npm install class-validator class-transformer

Now, create a simple DTO for user creation:

import { IsNotEmpty, IsEmail, Length } from 'class-validator';

class CreateUserDto {
    @IsNotEmpty()
    @IsEmail()
    public email: string;

    @IsNotEmpty()
    @Length(8, 20)
    public password: string;
}

Using Validation Pipes

NestJS provides a ValidationPipe that automatically applies the validation rules to incoming client payloads. You can set it up globally or at the controller and route level.

import { ValidationPipe } from '@nestjs/common';

// Global scope
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}

// Controller level
@UsePipes(new ValidationPipe())
export class UsersController {}

// Route level
@Post()
@UsePipes(new ValidationPipe())
async create(@Body() createUserDto: CreateUserDto) {}

Advanced Custom Validation

For more complex validation logic, NestJS allows you to create custom validators. Extend with ‘ValidatorConstraintInterface’ to create bespoke validation rules.

import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';

@ValidatorConstraint({ async: true })
export class IsUniqueConstraint implements ValidatorConstraintInterface {
  validate(value: any, args: ValidationArguments) {
    // Implement uniqueness logic here
  }
}

export function IsUnique(validationOptions?) {
  return function (object: Object, propertyName: string) {
    registerDecorator({
      target: object.constructor,
      propertyName: propertyName,
      options: validationOptions,
      constraints: [],
      validator: IsUniqueConstraint,
    });
  };
}

Conclusion

Validating data in NestJS is a scalable process thanks to its rich decorator-based validation system. By mastering DTOs, using the ValidationPipe efficiently, and employing custom validators, developers can ensure that their NestJS applications robustly handle all user inputs before they reach business logic.