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

type-validation.mddocs/

Type Validation

Type validation decorators ensure values are of the correct JavaScript/TypeScript primitive types. These decorators provide runtime type checking that complements TypeScript's compile-time type system, making them essential for validating data from external sources like APIs, user input, or parsed files.

Capabilities

Primitive Type Validation

Validate that values match expected JavaScript primitive types.

/**
 * Check that value is a string
 * @param validationOptions - Validation configuration options
 */
@IsString(validationOptions?: ValidationOptions): PropertyDecorator;

/**
 * Check that value is a number (including NaN and Infinity)
 * @param options - Number validation options
 * @param validationOptions - Validation configuration options
 */
@IsNumber(options?: IsNumberOptions, validationOptions?: ValidationOptions): PropertyDecorator;

/**
 * Check that value is a boolean
 * @param validationOptions - Validation configuration options
 */
@IsBoolean(validationOptions?: ValidationOptions): PropertyDecorator;

/**
 * Check that value is a Date object
 * @param validationOptions - Validation configuration options
 */
@IsDate(validationOptions?: ValidationOptions): PropertyDecorator;

/**
 * Check that value is an array
 * @param validationOptions - Validation configuration options
 */
@IsArray(validationOptions?: ValidationOptions): PropertyDecorator;

/**
 * Check that value is an object (and not null)
 * @param validationOptions - Validation configuration options
 */
@IsObject(validationOptions?: ValidationOptions): PropertyDecorator;

Numeric Type Validation

Specialized validation for numeric types with additional constraints.

/**
 * Check that value is an integer (whole number)
 * @param validationOptions - Validation configuration options
 */
@IsInt(validationOptions?: ValidationOptions): PropertyDecorator;

/**
 * Options for number validation
 */
interface IsNumberOptions {
  /** Allow NaN (default: false) */
  allowNaN?: boolean;
  /** Allow Infinity (default: false) */
  allowInfinity?: boolean;
  /** Maximum number of decimal places */
  maxDecimalPlaces?: number;
}

Enum Validation

Validate that values are members of specific enumerations.

/**
 * Check that value is a member of the specified enum
 * @param entity - Enum object to validate against
 * @param validationOptions - Validation configuration options
 */
@IsEnum(entity: object, validationOptions?: ValidationOptions): PropertyDecorator;

Usage Examples

Basic Type Validation

import { IsString, IsNumber, IsBoolean, IsDate, IsArray, IsObject } from "class-validator";

class DataModel {
  @IsString()
  name: string;
  
  @IsNumber()
  age: number;
  
  @IsBoolean()
  isActive: boolean;
  
  @IsDate()
  createdAt: Date;
  
  @IsArray()
  tags: string[];
  
  @IsObject()
  metadata: object;
}

// Usage
const data = new DataModel();
data.name = "John Doe";
data.age = 25;
data.isActive = true;
data.createdAt = new Date();
data.tags = ["user", "premium"];
data.metadata = { source: "api" };

Integer Validation

import { IsInt, IsNumber } from "class-validator";

class CounterModel {
  @IsInt()
  count: number; // Must be whole number
  
  @IsNumber({ maxDecimalPlaces: 2 })
  price: number; // Can have up to 2 decimal places
  
  @IsNumber({ allowNaN: false, allowInfinity: false })
  score: number; // Finite number only
}

const counter = new CounterModel();
counter.count = 42; // Valid
counter.price = 19.99; // Valid
counter.score = 85.5; // Valid

// These would fail validation:
// counter.count = 3.14; // Not an integer
// counter.price = 19.999; // Too many decimal places
// counter.score = NaN; // NaN not allowed

Enum Validation

import { IsEnum } from "class-validator";

enum UserRole {
  ADMIN = "admin",
  USER = "user",
  MODERATOR = "moderator"
}

enum Status {
  ACTIVE = 1,
  INACTIVE = 0,
  PENDING = 2
}

class User {
  @IsString()
  name: string;
  
  @IsEnum(UserRole)
  role: UserRole;
  
  @IsEnum(Status)
  status: Status;
}

const user = new User();
user.name = "Alice";
user.role = UserRole.ADMIN; // Valid
user.status = Status.ACTIVE; // Valid

// These would fail validation:
// user.role = "invalid-role"; // Not in UserRole enum
// user.status = 99; // Not in Status enum

Array Type Validation

import { IsArray, ArrayNotEmpty, ValidateNested } from "class-validator";

class Category {
  @IsString()
  name: string;
}

class Product {
  @IsString()
  name: string;
  
  @IsArray()
  @ArrayNotEmpty()
  tags: string[];
  
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => Category)
  categories: Category[];
}

const product = new Product();
product.name = "Laptop";
product.tags = ["electronics", "computers"]; // Valid array of strings
product.categories = [
  { name: "Electronics" },
  { name: "Computers" }
]; // Valid array of Category objects

Object Type Validation

import { IsObject, ValidateNested, IsNotEmptyObject } from "class-validator";

class Address {
  @IsString()
  street: string;
  
  @IsString()
  city: string;
}

class User {
  @IsString()
  name: string;
  
  @IsObject()
  @IsNotEmptyObject()
  preferences: object; // Any non-empty object
  
  @IsObject()
  @ValidateNested()
  @Type(() => Address)
  address: Address; // Specific object type with validation
}

const user = new User();
user.name = "Bob";
user.preferences = { theme: "dark", notifications: true }; // Valid object
user.address = { street: "123 Main St", city: "Anytown" }; // Valid Address object

Runtime Type Checking for API Data

import { IsString, IsNumber, IsBoolean, IsDate, IsArray, IsOptional } from "class-validator";

class ApiResponse {
  @IsString()
  id: string;
  
  @IsString()
  name: string;
  
  @IsNumber()
  value: number;
  
  @IsBoolean()
  active: boolean;
  
  @IsDate()
  @Type(() => Date)
  timestamp: Date;
  
  @IsArray()
  @IsString({ each: true })
  tags: string[];
  
  @IsOptional()
  @IsObject()
  metadata?: object;
}

// Function to validate API response
async function processApiData(rawData: any): Promise<ApiResponse> {
  const response = Object.assign(new ApiResponse(), rawData);
  const errors = await validate(response);
  
  if (errors.length > 0) {
    throw new Error(`Invalid API data: ${errors.map(e => e.toString()).join(', ')}`);
  }
  
  return response;
}

Form Data Validation

import { IsString, IsNumber, IsBoolean, IsEnum, IsOptional } from "class-validator";

enum Gender {
  MALE = "male",
  FEMALE = "female",
  OTHER = "other"
}

class UserRegistrationForm {
  @IsString()
  @Length(2, 50)
  firstName: string;
  
  @IsString()
  @Length(2, 50)
  lastName: string;
  
  @IsNumber()
  @Min(13)
  @Max(120)
  age: number;
  
  @IsEnum(Gender)
  gender: Gender;
  
  @IsBoolean()
  agreeToTerms: boolean;
  
  @IsOptional()
  @IsString()
  @Length(0, 500)
  bio?: string;
}

// Usage with form data
function validateFormData(formData: any): Promise<ValidationError[]> {
  const form = Object.assign(new UserRegistrationForm(), {
    firstName: formData.firstName,
    lastName: formData.lastName,
    age: parseInt(formData.age), // Convert string to number
    gender: formData.gender,
    agreeToTerms: formData.agreeToTerms === 'true', // Convert string to boolean
    bio: formData.bio
  });
  
  return validate(form);
}

Common Validation Patterns

Mixed Type Arrays

import { IsArray, ValidateNested } from "class-validator";

class MixedContent {
  @IsString()
  type: string;
  
  @IsString()
  value: string;
}

class Document {
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => MixedContent)
  content: MixedContent[];
}

Conditional Type Validation

import { ValidateIf, IsString, IsNumber } from "class-validator";

class FlexibleData {
  @IsString()
  dataType: 'string' | 'number';
  
  @ValidateIf(o => o.dataType === 'string')
  @IsString()
  stringValue?: string;
  
  @ValidateIf(o => o.dataType === 'number')
  @IsNumber()
  numberValue?: number;
}

Nested Object Type Validation

import { IsObject, ValidateNested, IsOptional, Type } from "class-validator";

class ContactInfo {
  @IsString()
  email: string;
  
  @IsOptional()
  @IsString()
  phone?: string;
}

class UserProfile {
  @IsString()
  username: string;
  
  @IsObject()
  @ValidateNested()
  @Type(() => ContactInfo)
  contact: ContactInfo;
  
  @IsOptional()
  @IsObject()
  @ValidateNested()
  @Type(() => ContactInfo)
  emergencyContact?: ContactInfo;
}