or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

advanced-patterns.mdcustom-extensions.mdindex.mdresults-data.mdschema-validation.mdvalidation-chains.mdvalidators-sanitizers.md
tile.json

schema-validation.mddocs/

Schema Validation

Object-based validation approach using checkSchema for complex validation rules and reusable validation logic. Schema validation provides a declarative way to define validation rules for entire objects.

Capabilities

Schema Function

Creates validation middleware from a schema object definition.

/**
 * Creates validation middleware from schema object
 * @param schema - Object mapping field names to validation schemas
 * @param defaultLocations - Default request locations to check if not specified in schema
 * @returns Array of ValidationChain instances
 */
function checkSchema(schema: Schema, defaultLocations?: Location[]): ValidationChain[];

interface Schema {
  [field: string]: ParamSchema;
}

type Location = 'body' | 'cookies' | 'headers' | 'params' | 'query';

Usage Examples:

import { checkSchema } from "express-validator";

// Basic schema validation
const userSchema = checkSchema({
  name: {
    trim: true,
    isLength: { options: { min: 2, max: 50 } },
    errorMessage: 'Name must be between 2 and 50 characters'
  },
  email: {
    isEmail: true,
    normalizeEmail: true,
    errorMessage: 'Must be a valid email address'
  },
  age: {
    isInt: { options: { min: 18, max: 120 } },
    toInt: true,
    errorMessage: 'Age must be between 18 and 120'
  }
});

// Use in Express route
app.post('/user', userSchema, (req, res) => {
  // Handle validation results
});

Parameter Schema Interface

Defines validation and sanitization rules for individual fields.

interface ParamSchema {
  // Location specification
  in?: Location | Location[];
  
  // Existence options
  exists?: boolean | {
    errorMessage?: string;
    checkNull?: boolean;
    checkFalsy?: boolean;
  };
  
  // Optional field configuration
  optional?: boolean | {
    nullable?: boolean;
    checkFalsy?: boolean;
  };
  
  // Array validation
  isArray?: boolean | {
    min?: number;
    max?: number;
  };
  
  // Conditional validation
  if?: (value: any, meta: Meta) => boolean;
  
  // Error handling
  errorMessage?: string;
  bail?: boolean;
  
  // Negation
  not?: boolean;
  
  // All validator methods (subset shown)
  isEmail?: boolean | EmailOptions;
  isInt?: boolean | IntOptions;
  isLength?: { min?: number; max?: number };
  isURL?: boolean | URLOptions;
  matches?: string | RegExp;
  custom?: CustomValidator;
  
  // All sanitizer methods (subset shown)
  trim?: boolean | string;
  escape?: boolean;
  normalizeEmail?: boolean | NormalizeEmailOptions;
  toInt?: boolean | number;
  toFloat?: boolean;
  customSanitizer?: CustomSanitizer;
}

Advanced Schema Patterns

Multi-Location Validation

Specify multiple request locations for field validation.

const authSchema = checkSchema({
  token: {
    // Check headers and query for token
    in: ['headers', 'query'],
    exists: true,
    isLength: { min: 20 },
    errorMessage: 'Valid token required'
  },
  userId: {
    // Check params and body for userId
    in: ['params', 'body'],
    isUUID: true,
    errorMessage: 'Valid user ID required'
  }
});

Optional and Nullable Fields

Handle optional fields with various null/undefined behaviors.

const profileSchema = checkSchema({
  bio: {
    optional: true, // Field is optional
    trim: true,
    isLength: { max: 500 }
  },
  avatar: {
    optional: { nullable: true }, // Allow null values
    isURL: true
  },
  preferences: {
    optional: { checkFalsy: true }, // Treat falsy values as missing
    isJSON: true
  }
});

Array Validation

Validate array fields and their elements.

const orderSchema = checkSchema({
  items: {
    isArray: { min: 1, max: 10 },
    errorMessage: 'Must provide 1-10 items'
  },
  'items.*.productId': {
    isUUID: true,
    errorMessage: 'Each item must have valid product ID'
  },
  'items.*.quantity': {
    isInt: { min: 1, max: 100 },
    toInt: true,
    errorMessage: 'Quantity must be between 1 and 100'
  },
  'items.*.price': {
    isDecimal: { decimal_digits: '2' },
    toFloat: true,
    errorMessage: 'Price must be valid decimal'
  }
});

Conditional Validation

Apply validation rules conditionally based on other field values.

const paymentSchema = checkSchema({
  paymentMethod: {
    isIn: { options: [['card', 'paypal', 'bank']] },
    errorMessage: 'Invalid payment method'
  },
  cardNumber: {
    if: (value, { req }) => req.body.paymentMethod === 'card',
    isCreditCard: true,
    errorMessage: 'Valid card number required for card payments'
  },
  paypalEmail: {
    if: (value, { req }) => req.body.paymentMethod === 'paypal',
    isEmail: true,
    errorMessage: 'Valid PayPal email required'
  },
  bankAccount: {
    if: (value, { req }) => req.body.paymentMethod === 'bank',
    matches: /^\d{8,12}$/,
    errorMessage: 'Valid bank account number required'
  }
});

Custom Validation in Schema

Integrate custom validation logic within schema definitions.

const registrationSchema = checkSchema({
  username: {
    trim: true,
    isLength: { min: 3, max: 20 },
    matches: /^[a-zA-Z0-9_]+$/,
    custom: async (value) => {
      const exists = await User.findByUsername(value);
      if (exists) {
        throw new Error('Username already taken');
      }
      return true;
    }
  },
  password: {
    isStrongPassword: {
      options: {
        minLength: 8,
        minLowercase: 1,
        minUppercase: 1,
        minNumbers: 1,
        minSymbols: 1
      }
    }
  },
  confirmPassword: {
    custom: (value, { req }) => {
      if (value !== req.body.password) {
        throw new Error('Password confirmation does not match');
      }
      return true;
    }
  }
});

Nested Object Validation

Validate nested object properties using dot notation.

const addressSchema = checkSchema({
  'address.street': {
    trim: true,
    notEmpty: true,
    errorMessage: 'Street address is required'
  },
  'address.city': {
    trim: true,
    isAlpha: true,
    errorMessage: 'City must contain only letters'
  },
  'address.zipCode': {
    matches: /^\d{5}(-\d{4})?$/,
    errorMessage: 'Invalid ZIP code format'
  },
  'address.country': {
    isISO31661Alpha2: true,
    errorMessage: 'Must be valid country code'
  }
});

Error Message Customization

Customize error messages at field and rule levels.

const validationSchema = checkSchema({
  email: {
    isEmail: {
      errorMessage: 'Please enter a valid email address'
    },
    normalizeEmail: true
  },
  age: {
    isInt: {
      options: { min: 18, max: 100 },
      errorMessage: 'Age must be a number between 18 and 100'
    },
    toInt: true
  },
  // Global error message for the field
  phone: {
    isMobilePhone: { options: 'en-US' },
    errorMessage: 'Please provide a valid US phone number'
  }
});

Schema Reusability

Define reusable schema components for consistent validation.

// Reusable field schemas
const commonFields = {
  email: {
    isEmail: true,
    normalizeEmail: true,
    errorMessage: 'Valid email required'
  },
  password: {
    isStrongPassword: {
      options: { minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1 }
    },
    errorMessage: 'Password must be strong'
  }
};

// User registration schema
const registerSchema = checkSchema({
  ...commonFields,
  firstName: {
    trim: true,
    isLength: { min: 2, max: 50 },
    errorMessage: 'First name must be 2-50 characters'
  },
  lastName: {
    trim: true,
    isLength: { min: 2, max: 50 },
    errorMessage: 'Last name must be 2-50 characters'
  }
});

// User login schema (reuses email field)
const loginSchema = checkSchema({
  email: commonFields.email,
  password: {
    notEmpty: true,
    errorMessage: 'Password is required'
  }
});