Validation Rules

Ack provides a rich set of built-in validation rules (constraints) that you can chain onto schema types to enforce specific requirements. Most constraints also accept an optional message: parameter to customize the error message upon failure (see Error Handling).

Common Constraints (Applicable to Multiple Types)

nullable()

Allows the value to be null in addition to the type's constraints.

final optionalName = Ack.string.nullable();
final optionalAge = Ack.int.nullable();

constrain(SchemaConstraint constraint)

Applies a custom SchemaConstraint. See the Custom Validation guide.

String Constraints

Apply these to Ack.string schemas.

minLength(int min)

Ensures the string has at least min characters.

Ack.string.minLength(5)

maxLength(int max)

Ensures the string has at most max characters.

Ack.string.maxLength(100)

length(int exactLength)

Ensures the string has exactly exactLength characters.

Ack.string.length(10)

isNotEmpty()

Ensures the string is not empty (''). Equivalent to minLength(1).

Ack.string.isNotEmpty()

matches(String pattern, {String? example})

Ensures the string fully matches the given regular expression pattern. The pattern is automatically anchored with ^ and $ if not already present.

// Simple alphanumeric pattern
Ack.string.matches(r'[a-zA-Z0-9]+')

// UUID pattern
Ack.string.matches(r'[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}')

contains(String pattern, {String? example})

Ensures the string contains the given pattern anywhere within it.

// Password must contain at least one uppercase letter
Ack.string.contains(r'[A-Z]')

// Password must contain at least one digit
Ack.string.contains(r'[0-9]')

isEmail()

Ensures the string is a valid email address format.

Ack.string.isEmail()

isUrl()

Ensures the string is a valid URL format.

Ack.string.isUrl()

isDate()

Ensures the string is a valid date format (YYYY-MM-DD).

Ack.string.isDate()

isDateTime()

Ensures the string is a valid date-time format (ISO 8601).

Ack.string.isDateTime()

isEnum(List<String> allowedValues)

Ensures the string is one of the allowedValues.

Ack.string.isEnum(['active', 'inactive', 'pending'])

Number Constraints (Int and Double)

Apply these to Ack.int and Ack.double schemas.

min(num limit, {bool exclusive = false})

Ensures the number is greater than (exclusive: true) or equal to (exclusive: false) the limit.

Ack.int.min(0) // >= 0
Ack.double.min(0, exclusive: true) // > 0

max(num limit, {bool exclusive = false})

Ensures the number is less than (exclusive: true) or equal to (exclusive: false) the limit.

Ack.int.max(100) // <= 100
Ack.double.max(100, exclusive: true) // < 100

positive()

Ensures the number is greater than 0. Shortcut for min(0, exclusive: true).

Ack.int.positive()
Ack.double.positive()

negative()

Ensures the number is less than 0. Shortcut for max(0, exclusive: true).

Ack.int.negative()
Ack.double.negative()

multipleOf(num factor)

Ensures the number is a multiple of the factor.

Ack.int.multipleOf(5) // Must be divisible by 5
Ack.double.multipleOf(0.01) // Allows up to 2 decimal places

List Constraints

Apply these to Ack.list schemas.

minItems(int min)

Ensures the list has at least min items.

Ack.list(Ack.string).minItems(1)

maxItems(int max)

Ensures the list has at most max items.

Ack.list(Ack.int).maxItems(10)

length(int exactLength)

Ensures the list has exactly exactLength items.

Ack.list(Ack.boolean).length(5)

isNotEmpty()

Ensures the list is not empty. Equivalent to minItems(1).

Ack.list(Ack.object({...})).isNotEmpty()

uniqueItems()

Ensures all items in the list are unique. Uses Set comparison.

Ack.list(Ack.string).uniqueItems()

Combining Constraints

You can chain multiple constraints together. They are evaluated in the order they are applied.

final usernameSchema = Ack.string
  .minLength(3)        // First check min length
  .maxLength(20)       // Then check max length
  .matches(r'[a-z0-9_]+') // Then check pattern (lowercase alphanumeric/underscore)
  .isNotEmpty();       // Redundant if minLength(>0) is used, but illustrates chaining

final quantitySchema = Ack.int
  .min(1)              // Must be at least 1
  .max(100)            // Must be at most 100
  .multipleOf(1);     // Must be an integer (redundant for Ack.int)