Skip to main content
This guide will help you create your first validation schema and validate data using PolyVal.

Basic validation

Let’s start with a simple example validating user data:
1

Import the validate function

Import the validate function from PolyVal:
import { validate } from 'polyval';
2

Define a validation schema

Create a schema that describes the structure and rules for your data:
const userSchema = {
  username: {
    type: 'string',
    required: true,
    min: 3,
    max: 20
  },
  email: {
    type: 'string',
    required: true,
    email: true
  },
  age: {
    type: 'number',
    min: 18
  }
};
3

Validate your data

Pass your schema, data, and options to the validate function:
const userData = {
  username: 'jo',
  email: 'invalid-email',
  age: 16
};

const errors = validate(userSchema, userData, { lang: 'en' });
console.log(errors);
This returns an array of error messages:
[
  "Username: Must be at least 3 characters long",
  "Email: Invalid email address",
  "Age: Must be at least 18"
]
When validation succeeds, validate() returns an empty array [].

User registration example

Here’s a complete real-world example of validating a user registration form:
import { validate, SimpleValidationSchema } from 'polyval';

// Define the schema
const userRegistrationSchema: SimpleValidationSchema = {
  username: {
    type: 'string',
    required: true,
    min: 3,
    max: 20,
    regex: '^[a-zA-Z0-9_]+$',
    customValidators: [
      {
        validator: (value: string) => {
          return value.toLowerCase() === 'admin' 
            ? 'Username admin is reserved' 
            : undefined;
        },
        messageKey: 'noAdminUsername'
      }
    ]
  },
  email: {
    type: 'string',
    required: true,
    email: true
  },
  password: {
    type: 'string',
    required: true,
    min: 8,
    regex: '^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]+$'
  },
  confirmPassword: {
    type: 'string',
    required: true,
    equals: 'password'
  },
  age: {
    type: 'number',
    min: 18
  },
  acceptTerms: {
    type: 'boolean',
    required: true,
    equals: true
  }
};

// Invalid data example
const invalidData = {
  username: 'a',
  email: 'invalid-email',
  password: 'weak',
  confirmPassword: 'different',
  age: 16,
  acceptTerms: false
};

const errors = validate(userRegistrationSchema, invalidData, { lang: 'en' });
errors.forEach(error => console.log(`- ${error}`));

// Valid data example
const validData = {
  username: 'johndoe',
  email: '[email protected]',
  password: 'Secure1@Password',
  confirmPassword: 'Secure1@Password',
  age: 25,
  acceptTerms: true
};

const noErrors = validate(userRegistrationSchema, validData, { lang: 'en' });
if (noErrors.length === 0) {
  console.log('✓ Validation successful!');
}

Multilingual validation

PolyVal supports multiple languages out of the box. Switch between languages by changing the lang option:
const errors = validate(schema, data, { lang: 'en' });
// ["Username: Must be at least 3 characters long"]

Custom error messages

Customize error messages to match your application’s tone and style:
const errors = validate(schema, data, {
  lang: 'en',
  customMessages: {
    string: {
      min: (min) => `At least ${min} characters required`,
      email: "Please enter a valid email address"
    },
    fields: {
      username: {
        min: (min) => `Username must have at least ${min} characters`,
        noAdminUsername: "Sorry, 'admin' is a reserved username"
      },
      password: {
        min: (min) => `Password must be at least ${min} characters long`,
        regex: "Password must include uppercase, lowercase, number and special character"
      },
      confirmPassword: {
        equals: "Passwords do not match"
      }
    }
  }
});
Custom messages defined at the field level take priority over general type-based messages.

Validation rules overview

PolyVal supports a variety of validation rules for different data types:
{
  type: 'string',
  required: boolean,
  min: number,           // Minimum length
  max: number,           // Maximum length
  length: number,        // Exact length
  email: boolean,        // Email format
  url: boolean,          // URL format
  uuid: boolean,         // UUID format
  regex: string,         // Regex pattern
  startsWith: string,    // Must start with
  endsWith: string,      // Must end with
  numeric: boolean       // Only numeric characters
}

Field comparison

Validate fields against each other using the equals and notEquals properties:
const schema = {
  password: {
    type: 'string',
    required: true,
    min: 8
  },
  confirmPassword: {
    type: 'string',
    required: true,
    equals: 'password'       // Must match password field
  },
  oldPassword: {
    type: 'string',
    required: true,
    notEquals: 'password'    // Must not match password field
  }
};
Field comparison validates the actual values, not the field configuration. Ensure both fields exist in your data object.

Next steps

API Reference

Explore all available validation rules and options

Custom Validators

Learn how to create custom validation logic

Error Messages

Master error message customization

Examples

See more real-world examples

Build docs developers (and LLMs) love