Nest JS class-validators complex examples to make life easier in project

Shivam Gupta
4 min readApr 10, 2023

Hello I am working in JavaScript related technologies from last 5+ years, currently working as Full stack engineer in Cardekho, Product based company in India.

From last 2 years, I started working In NestJS which is a typescript based framework. I developed 3 microservices using NestJs in a single project —

  1. Http Api Microservice
  2. Cron Microservice
  3. Consumer Microservice

On every micro service, We need to write class validators to validate input parameters, API Request Body & Query Params.

IN some cases class-validators are very typical and no documentation found , if you want to perform some complex validation, let me share some of great examples may made your life easier

Validate Array Of Mobile numbers

Input [“abc”, “8789”], error: “each value in mobile_numbers must match ^[5–9][0–9]{9}$ regular expression”

Validate Array Of objects

Input has buttons array with an Object
Example class validator example

Lets go more deeper in class validators —

1. Validating String

Any String

// example.dto.ts
import {
IsString,
IsNotEmpty,
MinLength,
MaxLength
} from 'class-validator'

export class AnyString {
@IsString()
@IsNotEmpty()
@MinLength(3)
@MaxLength(65)
userName: string
}

Specific String

// example.dto.tsty
import {
ArrayNotEmpty,
IsArray,
IsIn
} from 'class-validator'

const weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];
export class SpecificString {
@IsArray()
@ArrayNotEmpty()
@IsIn(weekdays)
day: string[]
}

Array of strings

// example.dto.ts
import {
ArrayNotEmpty,
Contains,
IsArray,
IsString,
Matches,
MaxLength
} from 'class-validator'

export class StringArray {
@IsArray()
@ArrayNotEmpty()
// check if every array item is string
@IsString({ each: true })
// Pass `each: true` when you want this validation to run on every array item
// Check if every array item has max length
@MaxLength(6, { each: true })
// Check if every array item is only alphabets
@Matches('^[a-zA-Z\\s]+$', undefined, { each: true })
// CHeck if every array item contains a text
@Contains('hello', { each: true })
stringArray: string[]
}

Array of Strings with a custom prefix

// example.dto.ts
import {
ArrayNotEmpty,
IsArray,
Validate,
ValidateNested,
ValidatorConstraint,
ValidatorConstraintInterface
} from 'class-validator'

@ValidatorConstraint({ name: 'arrayPrefixValidator' })
export class ArrayPrefixValidator implements ValidatorConstraintInterface {
validate(values: string[] = []): boolean {
if (values.length) {
return values.every((value) => value.startsWith('str-'))
}
return false
}
}
export class StringArray {
@IsArray()
@ArrayNotEmpty()
// Check if every array item contains a prefix str-
@Validate(ArrayPrefixValidator, { message: 'No str- prefix' })
stringArray: string[]
}

2️. Validating Number

Any number

import {
IsNumber,
IsNotEmpty,
MinLength,
MaxLength
} from 'class-validator'
export class AnyString {
@IsNumber()
@IsNotEmpty()
@MinLength(3)
@MaxLength(65)
userName: string
}

Specific Number

import {
IsNumber,
IsNotEmpty,
MinLength,
MaxLength,
ValidatorConstraint,
ValidatorConstraintInterface
} from 'class-validator'
@ValidatorConstraint({ name: 'isDividedBy17' })
export class IsDividedBy17 implements ValidatorConstraintInterface {
validate(value: number): boolean {
if (value {
return value % 17 === 0
}
return false
}
}
export class SpecificNumber {
@IsNumber()
@IsNotEmpty()
// Check if number is divisible by 17
@Validate(IsDividedBy17, { message: 'No divided by 17' })
specificNumber: number
}

Array of numbers

import {
IsNumber,
IsNotEmpty,
MinLength,
MaxLength,
ValidatorConstraint,
ValidatorConstraintInterface
} from 'class-validator'

@ValidatorConstraint({ name: 'isEvenNumber' })
export class IsEvenNumber implements ValidatorConstraintInterface {
validate(numbers: number): boolean {
if (numbers {
return numbers.every(number => number % 2 === 0)
}
return false
}
}
export class SpecificNumber {
@IsNumber()
@IsNotEmpty()
// Check if everynumber is even
@Validate(IsEvenNumber, { message: 'No divided by 17' })
numbersList: number[]
}

3️. Custom Object

For example you have a payload like below

{
jsom movies: [{
name: "The jurassic park",
yearOfRelease: 1999,
languages: ["en"]
gener: ["sci-fi", "thriller"]
},
{
name: "The Croods",
yearOfRelease: 2012,
languages: ["en", "fr", "es"]
gener: ["animation", "kids"]
}]
}
import {
IsNumber,
IsNotEmpty,
MinLength,
MaxLength,
ValidatorConstraint,
ValidatorConstraintInterface
} from 'class-validator'

@ValidatorConstraint({ name: 'isEvenNumber' })
export class IsEvenNumber implements ValidatorConstraintInterface {
validate(numbers: number): boolean {
if (numbers {
return numbers.every(number => number % 2 === 0)
}
return false
}
}
const validLanguages = ["en", "es", "fr"]
const validGeneres = ["sci-fi", "thriller", "animation", "horror", "vintage"]
// 💡 Types here
export class Movie {
@IsString()
@IsNotEmpty()
@ISRequired()
name: string
@IsNotEmpty()
@IsNumber()
@ISRequired()
yearOfRelease: number
@IsNotEmpty()
@IsString()
@IsIn(validLanguages)
@ISRequired()
languages: string[]
@IsNotEmpty()
@IsString()
@IsIn(validGeneres)
@ISRequired()
genre: string[]
}
export class MoviesList {
@IsArray()
@ArrayNotEmpty()
@Type(() => Movie)
movies: Movie[]
}

Please write in comment section if this was helpful in your use case, also u can write if need any help in your project.

References

--

--

Shivam Gupta

Full Stack Engineer (Web/App) working on different JS Technologies & frameworks— Angular, Node, Typescript, Ionic, Firebase, AWS, ElK...Love to write cool stuff