or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

array-object-validation.mdcommon-decorators.mdcore-validation.mdcustom-validation-schema.mdindex.mdnumber-date-validation.mdstring-validation.mdtype-validation.md
tile.json

array-object-validation.mddocs/

Array and Object Validation

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.

Capabilities

Array Size Validation

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;

Array Content Validation

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;

Object Structure Validation

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;

Usage Examples

Basic Array Size Validation

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 size

Array Content Validation

import { 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"

Array Uniqueness Validation

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 ID

Object Emptiness Validation

import { 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)

Instance Validation

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 instance

Complex Array Validation with Nested Objects

import { 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;

Multi-dimensional Array Validation

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 matrix

Conditional Array Validation

import { 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"]; // Optional

Object Validation with Custom Properties

import { 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')

Array of Mixed Content Types

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" }
];

Common Validation Patterns

Pagination Array Validation

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;
}

Tag and Category Validation

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[];
}

Hierarchical Data Validation

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;
}