🛠️ Built-in Validation Rules
Base Rules
typescript
r.required('Custom message') // Field is mandatory
r.email() // Valid email format
r.minLength(5) // Minimum string length
r.maxLength(100) // Maximum string length
r.numeric() // Only digits allowed
r.regex(/pattern/, 'message') // Custom regex pattern
r.oneOf(['a', 'b', 'c']) // Must be one of the specified valuesNumeric Rules
typescript
r.minValue(0) // Minimum value
r.maxValue(100) // Maximum value
r.between(0, 100) // Inclusive range of valuesCross-field Rules
typescript
r.sameAs('password') // Must match another field's value
r.dateAfter('startDate') // Date must be after another field's date
r.requiredIf('type', 'business') // Required if another field matches a specific valueFile Rules
typescript
r.fileRequired() // File selection is mandatory
r.fileSize(5 * 1024 * 1024) // Maximum file size (5MB)
r.fileType(['.jpg', '.png']) // Allowed file extensions
r.fileCount(1, 5) // Range for number of filesArray Rules
typescript
r.arrayRequired() // Checks if value is an array with at least one element
r.arrayMinLength(1) // Minimum array length
r.arrayMaxLength(10) // Maximum array lengthNote: arrayRequired() and arrayMinLength(1) function identically, but arrayRequired() provides a more semantic name for mandatory arrays.
Advanced Rules
typescript
// Remote validation with debouncing
r.remote(
async username => {
const response = await fetch(`/api/check-username/${username}`)
return response.ok
},
'Username is already taken',
500
)
// Custom validation
r.custom((value, allValues) => {
return value.includes(allValues.domain)
}, 'Invalid format')