Common validation decorators provide essential functionality for conditional validation, value checking, and geographic validation. These decorators form the foundation of most validation scenarios and are frequently used in combination with other validators.
Control when and how validation is applied to properties.
/**
* Skip validation if property value is null or undefined
* @param validationOptions - Validation configuration options
*/
@IsOptional(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Validate property only if condition function returns true
* @param condition - Function that determines if validation should run
* @param validationOptions - Validation configuration options
*/
@ValidateIf(condition: (object: any, value: any) => boolean, validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Validate nested object or array of objects using their own decorators
* @param validationOptions - Validation configuration options
*/
@ValidateNested(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Validate that value is defined (not null and not undefined)
* @param validationOptions - Validation configuration options
*/
@IsDefined(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Validate promise results when they resolve
* @param validationOptions - Validation configuration options
*/
@ValidatePromise(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Allow property in whitelist validation (mark as valid)
* @param validationOptions - Validation configuration options
*/
@Allow(validationOptions?: ValidationOptions): PropertyDecorator;Usage Examples:
import { IsOptional, ValidateIf, ValidateNested, IsDefined, IsNotEmpty, IsEmail } from "class-validator";
class Address {
@IsNotEmpty()
street: string;
@IsNotEmpty()
city: string;
}
class User {
@IsDefined()
@IsNotEmpty()
name: string;
@IsEmail()
email: string;
@IsOptional()
@IsNotEmpty()
nickname?: string;
@ValidateIf((object, value) => object.hasAddress === true)
@ValidateNested()
address?: Address;
hasAddress: boolean;
}
const user = new User();
user.name = "John";
user.email = "john@example.com";
user.hasAddress = true;
user.address = new Address();
user.address.street = "123 Main St";
user.address.city = "Anytown";Check values against specific criteria or constraints.
/**
* Check that value is not empty (not null, undefined, empty string, empty array, or empty object)
* @param validationOptions - Validation configuration options
*/
@IsNotEmpty(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value is empty (null, undefined, empty string, empty array, or empty object)
* @param validationOptions - Validation configuration options
*/
@IsEmpty(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value is in the allowed array of values
* @param values - Array of allowed values
* @param validationOptions - Validation configuration options
*/
@IsIn(values: any[], validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value is not in the forbidden array of values
* @param values - Array of forbidden values
* @param validationOptions - Validation configuration options
*/
@IsNotIn(values: any[], validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value exactly equals the comparison value
* @param comparison - Value to compare against
* @param validationOptions - Validation configuration options
*/
@Equals(comparison: any, validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value does not equal the comparison value
* @param comparison - Value to compare against
* @param validationOptions - Validation configuration options
*/
@NotEquals(comparison: any, validationOptions?: ValidationOptions): PropertyDecorator;Usage Examples:
import { IsNotEmpty, IsEmpty, IsIn, IsNotIn, Equals, NotEquals } from "class-validator";
class Product {
@IsNotEmpty()
name: string;
@IsIn(['active', 'inactive', 'pending'])
status: string;
@IsNotIn(['admin', 'system', 'root'])
category: string;
@Equals('v1.0')
version: string;
@NotEquals(0)
price: number;
@IsEmpty()
deletedAt?: Date;
}
const product = new Product();
product.name = "Laptop";
product.status = "active";
product.category = "electronics";
product.version = "v1.0";
product.price = 999.99;Validate geographic coordinates and location data.
/**
* Check that value is a valid latitude coordinate (-90 to 90)
* @param validationOptions - Validation configuration options
*/
@IsLatitude(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value is a valid longitude coordinate (-180 to 180)
* @param validationOptions - Validation configuration options
*/
@IsLongitude(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value is a valid lat,long coordinate string
* @param validationOptions - Validation configuration options
*/
@IsLatLong(validationOptions?: ValidationOptions): PropertyDecorator;Usage Examples:
import { IsLatitude, IsLongitude, IsLatLong } from "class-validator";
class Location {
@IsLatitude()
latitude: number;
@IsLongitude()
longitude: number;
}
class GeoPoint {
@IsLatLong()
coordinates: string; // Format: "40.7128,-74.0060"
}
const location = new Location();
location.latitude = 40.7128;
location.longitude = -74.0060;
const geoPoint = new GeoPoint();
geoPoint.coordinates = "40.7128,-74.0060";Core decorators for building custom validators and advanced validation scenarios.
/**
* Core decorator for building custom validation decorators
* @param options - Validation configuration with validator function
* @param validationOptions - Standard validation options
*/
@ValidateBy(options: ValidateByOptions, validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Validate using a custom constraint class
* @param constraintClass - Class implementing ValidatorConstraintInterface
* @param constraints - Array of constraint values passed to validator
* @param validationOptions - Standard validation options
*/
@Validate(constraintClass: Function, constraints?: any[], validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Options for ValidateBy decorator
*/
interface ValidateByOptions {
/** Name of the validation */
name: string;
/** Validator function */
validator: {
validate(value: any, args?: ValidationArguments): boolean | Promise<boolean>;
defaultMessage?(args?: ValidationArguments): string;
};
/** Whether validation is async */
async?: boolean;
/** Constraint values */
constraints?: any[];
}
/**
* Interface for custom constraint classes
*/
interface ValidatorConstraintInterface {
/**
* Method to be called to perform custom validation over given value
*/
validate(value: any, validationArguments?: ValidationArguments): boolean | Promise<boolean>;
/**
* Gets default message when validation fails
*/
defaultMessage?(validationArguments?: ValidationArguments): string;
}Usage Examples:
import { ValidateBy, Validate, ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from "class-validator";
// Using ValidateBy for simple custom validation
class User {
@ValidateBy({
name: "isOddNumber",
validator: {
validate(value: any) {
return typeof value === "number" && value % 2 === 1;
},
defaultMessage() {
return "Value must be an odd number";
}
}
})
favoriteNumber: number;
}
// Using custom constraint class
@ValidatorConstraint({ name: "isLongerThan", async: false })
class IsLongerThanConstraint implements ValidatorConstraintInterface {
validate(value: any, args: ValidationArguments) {
const [relatedPropertyName] = args.constraints;
const relatedValue = (args.object as any)[relatedPropertyName];
return typeof value === "string" && typeof relatedValue === "string" && value.length > relatedValue.length;
}
defaultMessage(args: ValidationArguments) {
const [relatedPropertyName] = args.constraints;
return `${args.property} must be longer than ${relatedPropertyName}`;
}
}
class Post {
title: string;
@Validate(IsLongerThanConstraint, ["title"])
text: string;
}import { ValidateIf, IsNotEmpty, IsEmail } from "class-validator";
class ContactInfo {
contactMethod: 'email' | 'phone';
@ValidateIf(o => o.contactMethod === 'email')
@IsEmail()
email?: string;
@ValidateIf(o => o.contactMethod === 'phone')
@IsNotEmpty()
phone?: string;
}import { ValidateNested, IsNotEmpty, IsEmail, Type } from "class-validator";
class Profile {
@IsNotEmpty()
displayName: string;
}
class User {
@IsEmail()
email: string;
@ValidateNested()
@Type(() => Profile)
profile: Profile;
@ValidateNested({ each: true })
@Type(() => Profile)
additionalProfiles: Profile[];
}import { IsOptional, IsNotEmpty, Length } from "class-validator";
class User {
@IsNotEmpty()
name: string;
@IsOptional()
@IsNotEmpty()
@Length(10, 500)
bio?: string; // Optional, but if provided must be non-empty and within length limits
}