Decorator-based property validation for classes.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
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;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;
}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;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" };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 allowedimport { 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 enumimport { 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 objectsimport { 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 objectimport { 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;
}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);
}import { IsArray, ValidateNested } from "class-validator";
class MixedContent {
@IsString()
type: string;
@IsString()
value: string;
}
class Document {
@IsArray()
@ValidateNested({ each: true })
@Type(() => MixedContent)
content: MixedContent[];
}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;
}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;
}