Dynz.

Validation rules

The complete reference for every built-in validation rule — string, number, date, array, file, and more.

Validation rules are attached to a schema via the fluent builder. Each rule is a plain object that validate() evaluates at runtime — not a JavaScript function — so rules survive serialization just like the rest of the schema.

Rules accept either static values (42, "alice@example.com") or expressions (d.ref(...), d.multiply(...)) as parameters. See Expressions for the full list.

Every rule accepts an optional code as the last argument. That string becomes error.code in the validation result, letting you map errors to custom messages in your UI without hardcoding the built-in codes.

d.string().min(2, 'name_too_short')
// error.code === 'name_too_short'

String rules

.min(length, code?)

The string must have at least length characters.

d.string().min(2)          // At least 2 characters
d.string().min(d.ref('minLength'))  // Dynamic minimum from another field

.max(length, code?)

The string must have at most length characters.

d.string().max(100)
d.string().min(1).max(50)

.email(code?)

The string must be a valid email address.

const email = d.string().email();

.regex(pattern, flags?, code?)

The string must match the given regular expression.

const slug     = d.string().regex('^[a-z0-9-]+$');
const hexColor = d.string().regex('^#[0-9a-fA-F]{6}$');
const phone    = d.string().regex('^\\+?[1-9]\\d{1,14}$');  // E.164

.equals(value, code?)

The string must equal value exactly. Accepts a static string or a d.ref().

// Password confirmation
d.string().equals(d.ref('password'), 'passwords_must_match')

// Fixed string match
d.string().equals('accepted')

.oneOf(values, code?)

The string must be one of the provided values.

d.string().oneOf(['red', 'green', 'blue'])

.includes(value, code?)

The string must contain value as a substring.

d.string().includes('@')  // Rough email check

.notIncludes(value, code?)

The string must not contain value.

d.string().notIncludes('badword')

.isNumeric(code?)

The string must consist entirely of numeric characters (0-9). Useful for PIN codes and numeric ID strings.

const pin = d.string().min(4).max(6).isNumeric();

Number rules

.min(value, code?)

The number must be greater than or equal to value. Accepts a static number or an expression.

d.number().min(0)        // Non-negative
d.number().min(1)        // Positive integer
d.number().min(d.ref('minAllowed'))

.max(value, code?)

The number must be less than or equal to value.

d.number().min(0).max(100)  // Percentage
d.number().max(d.ref('income'))  // Loan can't exceed income

.maxPrecision(decimals, code?)

The number can have at most decimals digits after the decimal point.

const price    = d.number().min(0).maxPrecision(2);  // e.g. 9.99 ✓, 9.999 ✗
const quantity = d.number().min(0).maxPrecision(0);  // Integers only

Date rules

.after(value, code?)

The date must be strictly after value (exclusive). Accepts a static Date or a d.ref().

d.date().after(new Date())           // Must be in the future
d.date().after(d.ref('startDate'), 'end_before_start')  // End after start

.before(value, code?)

The date must be strictly before value (exclusive).

const birthDate = d.date().before(new Date())  // Must be in the past

.minDate(value, code?)

The date must be on or after value (inclusive).

d.date().minDate(new Date('2024-01-01'))

.maxDate(value, code?)

The date must be on or before value (inclusive).

d.date().minDate(new Date('2024-01-01')).maxDate(new Date('2024-12-31'))

Array rules

.min(count, code?)

The array must have at least count items.

d.array(d.string()).min(1)   // Non-empty
d.array(d.string()).min(3)   // At least 3 items

.max(count, code?)

The array must have at most count items.

d.array(d.file()).min(1).max(5)  // 1 to 5 files

File rules

.maxSize(bytes, code?)

The file must be smaller than bytes bytes.

d.file().maxSize(2 * 1024 * 1024)   // 2 MB
d.file().maxSize(10 * 1024 * 1024)  // 10 MB

.minSize(bytes, code?)

The file must be at least bytes bytes.

d.file().minSize(1024)  // At least 1 KB (rejects empty files)

.mimeType(type | types, code?)

The file must match the given MIME type or types.

d.file().mimeType('image/jpeg')
d.file().mimeType(['image/jpeg', 'image/png', 'image/webp'])
d.file().mimeType(['application/pdf', 'application/msword'])

Conditional rules — .when(predicate, callback)

All schema types support .when(), which applies a set of rules only when a predicate is true. The callback receives a rule builder and must return it.

d.string()
  .when(d.eq(d.ref('country'), 'US'), (b) =>
    b.regex('^\\d{5}(-\\d{4})?$', undefined, 'invalid_us_zip')
  )
  .when(d.eq(d.ref('country'), 'CA'), (b) =>
    b.regex('^[A-Z]\\d[A-Z] ?\\d[A-Z]\\d$', 'i', 'invalid_ca_postal')
  )

Multiple .when() chains are applied independently. A rule fires only when its predicate evaluates to true.

The .when() callback builder only exposes rule methods, not property setters. Use setRequired, setIncluded, and setMutable at the top level instead.


Custom rules — .custom(name, params?, code?)

Attach a named custom rule whose implementation you provide at validation time. See Custom rules for the full guide.

d.string().custom('profanity-filter')
d.string().custom('password-strength', { minScore: 3 })
d.number().custom('in-stock', { productId: d.ref('productId') })

On this page