Array and object validation decorators provide comprehensive validation for collections and structured data. These validators handle size constraints, content validation, uniqueness requirements, and structural checking, making them essential for validating complex data structures and ensuring data integrity.
Control array dimensions with size constraints and emptiness checks.
/**
* Check that array is not empty
* @param validationOptions - Validation configuration options
*/
@ArrayNotEmpty(validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that array has at least minimum number of elements
* @param min - Minimum array size (inclusive)
* @param validationOptions - Validation configuration options
*/
@ArrayMinSize(min: number, validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that array has at most maximum number of elements
* @param max - Maximum array size (inclusive)
* @param validationOptions - Validation configuration options
*/
@ArrayMaxSize(max: number, validationOptions?: ValidationOptions): PropertyDecorator;Validate array contents and element relationships.
/**
* Check that array contains all specified values
* @param values - Array of values that must be present
* @param validationOptions - Validation configuration options
*/
@ArrayContains(values: any[], validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that array does not contain any of the specified values
* @param values - Array of values that must not be present
* @param validationOptions - Validation configuration options
*/
@ArrayNotContains(values: any[], validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that all array elements are unique
* @param identifier - Optional function to extract comparison key from elements
* @param validationOptions - Validation configuration options
*/
@ArrayUnique(identifier?: (o: any) => any, validationOptions?: ValidationOptions): PropertyDecorator;Validate object properties and structure.
/**
* Check that object is not empty (has at least one property)
* @param options - Object validation options
* @param validationOptions - Validation configuration options
*/
@IsNotEmptyObject(options?: {nullable?: boolean}, validationOptions?: ValidationOptions): PropertyDecorator;
/**
* Check that value is an instance of specified class
* @param targetType - Constructor function of expected class
* @param validationOptions - Validation configuration options
*/
@IsInstance(targetType: new (...args: any[]) => any, validationOptions?: ValidationOptions): PropertyDecorator;import { ArrayNotEmpty, ArrayMinSize, ArrayMaxSize } from "class-validator";
class TaskList {
@ArrayNotEmpty()
tasks: string[]; // Must have at least one task
@ArrayMinSize(1)
@ArrayMaxSize(10)
priorities: string[]; // Between 1 and 10 priorities
@ArrayMinSize(2)
assignees: string[]; // At least 2 assignees required
}
const taskList = new TaskList();
taskList.tasks = ["Complete project", "Review code"]; // Valid
taskList.priorities = ["high", "medium", "low"]; // Valid
taskList.assignees = ["Alice", "Bob", "Charlie"]; // Valid
// These would fail validation:
// taskList.tasks = []; // Empty array not allowed
// taskList.priorities = []; // Below minimum size
// taskList.assignees = ["Alice"]; // Below minimum sizeimport { ArrayContains, ArrayNotContains, IsArray } from "class-validator";
class SecurityConfiguration {
@IsArray()
@ArrayContains(["admin", "user"]) // Must contain both "admin" and "user"
requiredRoles: string[];
@IsArray()
@ArrayNotContains(["root", "system"]) // Must not contain restricted roles
allowedRoles: string[];
}
const config = new SecurityConfiguration();
config.requiredRoles = ["admin", "user", "guest"]; // Valid (contains required roles)
config.allowedRoles = ["admin", "user", "guest", "moderator"]; // Valid (no restricted roles)
// These would fail validation:
// config.requiredRoles = ["admin"]; // Missing "user"
// config.allowedRoles = ["admin", "user", "root"]; // Contains restricted "root"import { ArrayUnique, IsArray } from "class-validator";
class UserProfile {
@IsArray()
@ArrayUnique()
tags: string[]; // All tags must be unique
@IsArray()
@ArrayUnique()
skillIds: number[]; // All skill IDs must be unique
}
class TeamMember {
name: string;
id: number;
}
class Team {
@IsArray()
@ArrayUnique((member: TeamMember) => member.id) // Unique by ID
members: TeamMember[];
@IsArray()
@ArrayUnique((member: TeamMember) => member.name) // Unique by name
leads: TeamMember[];
}
const profile = new UserProfile();
profile.tags = ["javascript", "typescript", "node"]; // Valid (all unique)
profile.skillIds = [1, 2, 3, 4]; // Valid (all unique)
const team = new Team();
team.members = [
{ name: "Alice", id: 1 },
{ name: "Bob", id: 2 }
]; // Valid (unique IDs)
// These would fail validation:
// profile.tags = ["javascript", "javascript"]; // Duplicate values
// team.members = [{ name: "Alice", id: 1 }, { name: "Bob", id: 1 }]; // Duplicate IDimport { IsNotEmptyObject, IsObject } from "class-validator";
class ConfigurationData {
@IsObject()
@IsNotEmptyObject()
settings: object; // Must be non-empty object
@IsObject()
@IsNotEmptyObject({ nullable: true })
optionalConfig?: object; // Can be null, but if present must be non-empty
}
const config = new ConfigurationData();
config.settings = { theme: "dark", language: "en" }; // Valid (non-empty object)
config.optionalConfig = { cache: true }; // Valid (non-empty object)
// These would fail validation:
// config.settings = {}; // Empty object not allowed
// config.optionalConfig = {}; // Empty object not allowed (but null would be OK)import { IsInstance, IsArray, ValidateNested } from "class-validator";
class Address {
street: string;
city: string;
}
class Person {
name: string;
}
class User {
@IsInstance(Person)
person: Person; // Must be instance of Person class
@IsInstance(Address)
address: Address; // Must be instance of Address class
@IsArray()
@IsInstance(Address, { each: true })
previousAddresses: Address[]; // Array where each element is Address instance
}
const user = new User();
user.person = new Person(); // Valid
user.address = new Address(); // Valid
user.previousAddresses = [new Address(), new Address()]; // Valid
// These would fail validation:
// user.person = { name: "John" }; // Plain object, not Person instance
// user.address = { street: "123 Main", city: "Town" }; // Plain object, not Address instanceimport { IsArray, ValidateNested, ArrayMinSize, ArrayMaxSize, ArrayUnique, Type } from "class-validator";
class Product {
@IsString()
@IsNotEmpty()
name: string;
@IsNumber()
@Min(0)
price: number;
@IsString()
category: string;
}
class ShoppingCart {
@IsArray()
@ArrayNotEmpty()
@ArrayMinSize(1)
@ArrayMaxSize(50)
@ValidateNested({ each: true })
@Type(() => Product)
@ArrayUnique((product: Product) => product.name) // Unique product names
items: Product[];
@IsNumber()
@Min(0)
totalValue: number;
}
const cart = new ShoppingCart();
cart.items = [
{ name: "Laptop", price: 999, category: "Electronics" },
{ name: "Mouse", price: 25, category: "Electronics" }
];
cart.totalValue = 1024;import { IsArray, ArrayMinSize, ArrayMaxSize, IsNumber } from "class-validator";
class Matrix {
@IsArray()
@ArrayMinSize(2)
@ArrayMaxSize(10)
@IsArray({ each: true })
@ArrayMinSize(2, { each: true })
@ArrayMaxSize(10, { each: true })
@IsNumber({}, { each: true })
data: number[][]; // 2D array with size constraints
}
const matrix = new Matrix();
matrix.data = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]; // Valid 3x3 matriximport { ValidateIf, IsArray, ArrayNotEmpty, ArrayMinSize } from "class-validator";
class EventConfiguration {
hasAttendees: boolean;
@ValidateIf(o => o.hasAttendees === true)
@IsArray()
@ArrayNotEmpty()
@ArrayMinSize(1)
attendeeList?: string[];
@ValidateIf(o => o.hasAttendees === false)
@IsArray()
alternativeContacts?: string[];
}
const eventWithAttendees = new EventConfiguration();
eventWithAttendees.hasAttendees = true;
eventWithAttendees.attendeeList = ["Alice", "Bob"]; // Required when hasAttendees is true
const eventWithoutAttendees = new EventConfiguration();
eventWithoutAttendees.hasAttendees = false;
eventWithoutAttendees.alternativeContacts = ["admin@example.com"]; // Optionalimport { IsObject, IsNotEmptyObject, ValidateBy } from "class-validator";
class CustomObjectValidator {
@IsObject()
@IsNotEmptyObject()
@ValidateBy({
name: "hasRequiredKeys",
validator: {
validate(value: any) {
return value &&
typeof value === 'object' &&
'id' in value &&
'name' in value;
},
defaultMessage() {
return "Object must have 'id' and 'name' properties";
}
}
})
requiredFields: object;
}
const validator = new CustomObjectValidator();
validator.requiredFields = { id: 1, name: "Test", extra: "value" }; // Valid
// validator.requiredFields = { id: 1 }; // Would fail (missing 'name')import { IsArray, ValidateNested, Type } from "class-validator";
class TextContent {
@IsString()
type: "text";
@IsString()
content: string;
}
class ImageContent {
@IsString()
type: "image";
@IsUrl()
url: string;
}
class Article {
@IsArray()
@ValidateNested({ each: true })
@Type(() => Object, {
discriminator: {
property: 'type',
subTypes: [
{ value: TextContent, name: 'text' },
{ value: ImageContent, name: 'image' }
]
}
})
content: (TextContent | ImageContent)[];
}
const article = new Article();
article.content = [
{ type: "text", content: "Hello world" },
{ type: "image", url: "https://example.com/image.jpg" }
];import { IsArray, ArrayMinSize, ArrayMaxSize, ValidateNested } from "class-validator";
class PaginatedResults<T> {
@IsArray()
@ArrayMaxSize(100) // Limit results per page
@ValidateNested({ each: true })
items: T[];
@IsNumber()
@Min(0)
total: number;
@IsNumber()
@Min(1)
page: number;
@IsNumber()
@Min(1)
@Max(100)
pageSize: number;
}import { IsArray, ArrayUnique, ArrayMaxSize, IsString } from "class-validator";
class ContentMetadata {
@IsArray()
@ArrayUnique()
@ArrayMaxSize(10)
@IsString({ each: true })
tags: string[];
@IsArray()
@ArrayMinSize(1)
@ArrayMaxSize(3)
@IsString({ each: true })
categories: string[];
}import { IsArray, ValidateNested, IsOptional } from "class-validator";
class TreeNode {
@IsString()
name: string;
@IsOptional()
@IsArray()
@ValidateNested({ each: true })
@Type(() => TreeNode)
children?: TreeNode[];
}
class Tree {
@ValidateNested()
@Type(() => TreeNode)
root: TreeNode;
}