Flexible rule definition system supporting various validation types, custom validators, and nested object validation.
Basic rule configuration interface defining validation parameters.
interface RuleItem {
type?: RuleType;
required?: boolean;
pattern?: RegExp | string;
min?: number;
max?: number;
len?: number;
enum?: Array<string | number | boolean | null | undefined>;
whitespace?: boolean;
fields?: Record<string, Rule>;
options?: ValidateOption;
defaultField?: Rule;
transform?: (value: Value) => Value;
message?: string | ((a?: string) => string);
asyncValidator?: AsyncValidatorFunction;
validator?: ValidatorFunction;
}
type Rule = RuleItem | RuleItem[];
type Rules = Record<string, Rule>;Specify the validation type for the field.
type?: RuleType;Usage Examples:
// String validation
{ type: "string", min: 5, max: 50 }
// Number validation
{ type: "number", min: 0, max: 100 }
// Email validation
{ type: "email" }
// Array validation
{ type: "array", min: 1, max: 10 }Mark fields as mandatory.
required?: boolean;Usage Example:
const rules = {
username: { type: "string", required: true },
bio: { type: "string", required: false } // Optional field
};Validate against regular expression patterns.
pattern?: RegExp | string;Usage Examples:
const rules = {
// RegExp object
username: {
type: "string",
pattern: /^[a-zA-Z0-9_]+$/
},
// String pattern
zipCode: {
type: "string",
pattern: "^\\d{5}(-\\d{4})?$"
}
};Set minimum constraints for numbers, strings, or arrays.
min?: number;Set maximum constraints for numbers, strings, or arrays.
max?: number;Specify exact length for strings or arrays.
len?: number;Usage Examples:
const rules = {
// String length constraints
password: { type: "string", min: 8, max: 50 },
// Exact length
zipCode: { type: "string", len: 5 },
// Number range
age: { type: "number", min: 0, max: 120 },
// Array length
tags: { type: "array", min: 1, max: 5 }
};Restrict values to a specific set of allowed options.
enum?: Array<string | number | boolean | null | undefined>;Usage Example:
const rules = {
status: {
type: "string",
enum: ["active", "inactive", "pending"]
},
priority: {
type: "number",
enum: [1, 2, 3, 4, 5]
}
};Check for whitespace-only strings.
whitespace?: boolean;Usage Example:
const rules = {
comment: {
type: "string",
required: true,
whitespace: true // Reject whitespace-only strings
}
};Define validation rules for nested object properties.
fields?: Record<string, Rule>;Usage Example:
const rules = {
user: {
type: "object",
required: true,
fields: {
name: { type: "string", required: true },
email: { type: "email", required: true },
profile: {
type: "object",
fields: {
age: { type: "number", min: 0 },
bio: { type: "string", max: 500 }
}
}
}
}
};Apply the same rule to all properties of an object or elements of an array.
defaultField?: Rule;Usage Examples:
const rules = {
// Array of strings
tags: {
type: "array",
defaultField: { type: "string", min: 1, max: 20 }
},
// Object with dynamic keys
metadata: {
type: "object",
defaultField: { type: "string" }
}
};Transform field values before validation.
transform?: (value: Value) => Value;Usage Examples:
const rules = {
email: {
type: "email",
transform: (value) => value?.toLowerCase?.() || value
},
name: {
type: "string",
transform: (value) => value?.trim?.() || value,
required: true
},
price: {
type: "number",
transform: (value) => typeof value === "string" ? parseFloat(value) : value,
min: 0
}
};Provide custom error messages for specific rules.
message?: string | ((a?: string) => string);Usage Examples:
const rules = {
// Static message
username: {
type: "string",
required: true,
message: "Username is required and must be a text value"
},
// Dynamic message function
age: {
type: "number",
min: 18,
message: (field) => `${field} must be at least 18 years old`
}
};Define custom validation logic with synchronous execution.
validator?: (
rule: InternalRuleItem,
value: Value,
callback: (error?: string | Error) => void,
source: Values,
options: ValidateOption
) => SyncValidateResult | void;Usage Example:
const rules = {
password: {
type: "string",
validator: (rule, value, callback) => {
if (!/(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(value)) {
callback("Password must contain uppercase, lowercase, and number");
} else {
callback(); // Success
}
}
}
};Define custom validation logic with asynchronous execution.
asyncValidator?: (
rule: InternalRuleItem,
value: Value,
callback: (error?: string | Error) => void,
source: Values,
options: ValidateOption
) => void | Promise<void>;Usage Examples:
const rules = {
// Promise-based async validator
username: {
type: "string",
asyncValidator: async (rule, value, callback) => {
try {
const exists = await checkUsernameExists(value);
if (exists) {
callback("Username already taken");
} else {
callback();
}
} catch (error) {
callback("Unable to validate username");
}
}
},
// Callback-based async validator
email: {
type: "email",
asyncValidator: (rule, value, callback) => {
validateEmailOnServer(value)
.then(() => callback())
.catch(() => callback("Email validation failed"));
}
}
};Apply multiple validation rules to a single field.
Usage Example:
const rules = {
username: [
{ type: "string", required: true },
{ min: 3, max: 20, message: "Username must be 3-20 characters" },
{ pattern: /^[a-zA-Z0-9_]+$/, message: "Username can only contain letters, numbers, and underscores" },
{
asyncValidator: async (rule, value, callback) => {
const available = await checkAvailability(value);
if (!available) {
callback("Username not available");
} else {
callback();
}
}
}
]
};Pass specific options to nested field validation.
options?: ValidateOption;Usage Example:
const rules = {
addresses: {
type: "array",
fields: {
street: { type: "string", required: true },
city: { type: "string", required: true }
},
options: {
first: true, // Stop on first error in nested validation
suppressWarning: true
}
}
};