or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

core-validation.mderror-handling.mdindex.mdjtd-schemas.mdkeywords-vocabularies.mdschema-2019.mdschema-2020.mdschema-management.mdstandalone-generation.mdtypescript-integration.md
tile.json

schema-2019.mddocs/

JSON Schema 2019-09 Support

Enhanced validation for JSON Schema Draft 2019-09 with dynamic references, unevaluated properties/items, and next generation features for advanced schema composition and validation.

Capabilities

Ajv2019 Constructor

Creates an Ajv validator instance configured for JSON Schema Draft 2019-09 with enhanced features automatically enabled.

/**
 * Creates Ajv validator for JSON Schema Draft 2019-09
 * @param options - Configuration options (dynamicRef, next, unevaluated enabled by default)
 */
constructor(options?: Options);

class Ajv2019 extends AjvCore {
  constructor(opts: Options = {}) {
    super({
      ...opts,
      dynamicRef: true,  // Automatically enabled
      next: true,        // Automatically enabled
      unevaluated: true, // Automatically enabled
    });
  }
}

Usage Examples:

import Ajv2019 from "ajv/dist/2019";

// Basic 2019-09 validator with enhanced features
const ajv = new Ajv2019();

// Custom options while maintaining 2019-09 features
const ajvCustom = new Ajv2019({
  allErrors: true,
  verbose: true,
  strict: false
});

Dynamic References

Support for $dynamicRef and $dynamicAnchor enabling runtime schema resolution based on the validation context.

// Dynamic reference syntax in schemas
interface DynamicRefSchema {
  $dynamicRef: string;        // Reference to dynamic anchor
  $dynamicAnchor?: string;    // Dynamic anchor definition
  [key: string]: any;
}

Usage Examples:

import Ajv2019 from "ajv/dist/2019";

const ajv = new Ajv2019();

// Base schema with dynamic anchor
const baseSchema = {
  $id: "https://example.com/base",
  $dynamicAnchor: "meta",
  type: "object",
  properties: {
    foo: { type: "string" }
  }
};

// Extended schema that overrides the dynamic anchor
const extendedSchema = {
  $id: "https://example.com/extended", 
  $dynamicAnchor: "meta",
  allOf: [
    { $ref: "https://example.com/base" }
  ],
  properties: {
    foo: { type: "string" },
    bar: { type: "number" }
  }
};

// Schema using dynamic reference
const userSchema = {
  $id: "https://example.com/user",
  type: "object",
  properties: {
    profile: { $dynamicRef: "#meta" }
  }
};

ajv.addSchema([baseSchema, extendedSchema, userSchema]);

// Dynamic resolution based on context
const validate = ajv.compile({
  allOf: [
    { $ref: "https://example.com/extended" },
    { $ref: "https://example.com/user" }
  ]
});

Unevaluated Properties and Items

Advanced handling of unevaluatedProperties and unevaluatedItems for comprehensive schema validation.

// Unevaluated keywords in schemas
interface UnevaluatedSchema {
  unevaluatedProperties?: boolean | AnySchema;
  unevaluatedItems?: boolean | AnySchema;
  [key: string]: any;
}

Usage Examples:

import Ajv2019 from "ajv/dist/2019";

const ajv = new Ajv2019();

// Schema with unevaluated properties control
const schema = {
  type: "object",
  properties: {
    name: { type: "string" }
  },
  if: {
    properties: { type: { const: "user" } }
  },
  then: {
    properties: {
      email: { type: "string", format: "email" }
    }
  },
  else: {
    properties: {
      code: { type: "string" }
    }
  },
  unevaluatedProperties: false  // Disallow any other properties
};

const validate = ajv.compile(schema);

// Valid: only evaluated properties
console.log(validate({
  name: "Alice",
  type: "user", 
  email: "alice@example.com"
})); // true

// Invalid: unevaluated property
console.log(validate({
  name: "Alice",
  type: "user",
  email: "alice@example.com", 
  extra: "not allowed"  // This will fail
})); // false

// Array example with unevaluated items
const arraySchema = {
  type: "array",
  prefixItems: [
    { type: "string" },
    { type: "number" }
  ],
  if: {
    minItems: 3
  },
  then: {
    items: { type: "boolean" }  // Additional items must be boolean
  },
  unevaluatedItems: false  // No other items allowed
};

Schema Composition Enhancements

Enhanced support for complex schema composition with proper evaluation tracking.

// Advanced composition schemas
interface CompositionSchema {
  if?: AnySchema;
  then?: AnySchema;
  else?: AnySchema;
  dependentSchemas?: { [property: string]: AnySchema };
  $defs?: { [key: string]: AnySchema };
  [key: string]: any;
}

Usage Examples:

import Ajv2019 from "ajv/dist/2019";

const ajv = new Ajv2019();

// Complex conditional schema
const productSchema = {
  $id: "https://example.com/product-2019",
  type: "object",
  properties: {
    type: { enum: ["physical", "digital", "service"] },
    name: { type: "string" },
    price: { type: "number", minimum: 0 }
  },
  required: ["type", "name", "price"],
  
  // Conditional requirements based on product type
  if: {
    properties: { type: { const: "physical" } }
  },
  then: {
    properties: {
      weight: { type: "number", minimum: 0 },
      dimensions: {
        type: "object",
        properties: {
          length: { type: "number" },
          width: { type: "number" },  
          height: { type: "number" }
        },
        required: ["length", "width", "height"]
      }
    },
    required: ["weight", "dimensions"]
  },
  else: {
    if: {
      properties: { type: { const: "digital" } }
    },
    then: {
      properties: {
        downloadUrl: { type: "string", format: "uri" },
        fileSize: { type: "integer", minimum: 1 }
      },
      required: ["downloadUrl", "fileSize"]
    },
    else: {
      // Service type
      properties: {
        duration: { type: "string" },
        location: { type: "string" }
      },
      required: ["duration"]
    }
  },
  
  unevaluated: false  // No additional properties beyond evaluated ones
};

const validate = ajv.compile(productSchema);

// Physical product
console.log(validate({
  type: "physical",
  name: "Laptop",
  price: 999.99,
  weight: 2.5,
  dimensions: { length: 30, width: 20, height: 2 }
})); // true

// Digital product  
console.log(validate({
  type: "digital",
  name: "Software",
  price: 49.99,
  downloadUrl: "https://example.com/download",
  fileSize: 1024000
})); // true

Reference Resolution Enhancements

Improved reference resolution with support for anchors and recursive schemas.

// Enhanced reference patterns
interface EnhancedRefSchema {
  $anchor?: string;         // Named anchor for reference
  $recursiveRef?: string;   // Recursive reference (deprecated in favor of $dynamicRef)
  $recursiveAnchor?: boolean; // Recursive anchor (deprecated)
  [key: string]: any;
}

Usage Examples:

import Ajv2019 from "ajv/dist/2019";

const ajv = new Ajv2019();

// Recursive schema using anchors
const treeSchema = {
  $id: "https://example.com/tree",
  $anchor: "node",
  type: "object",
  properties: {
    value: { type: "string" },
    children: {
      type: "array",
      items: { $ref: "#node" }  // Recursive reference
    }
  },
  required: ["value"]
};

ajv.addSchema(treeSchema);

const validate = ajv.getSchema("https://example.com/tree");

// Validate recursive tree structure
const treeData = {
  value: "root",
  children: [
    { 
      value: "child1",
      children: [
        { value: "grandchild1" },
        { value: "grandchild2" }
      ]
    },
    { value: "child2" }
  ]
};

console.log(validate(treeData)); // true

Migration from Draft 7

Key differences when migrating from Draft 7 to 2019-09:

  1. New Keywords: unevaluatedProperties, unevaluatedItems, dependentSchemas, dependentRequired
  2. Dynamic References: Replace $recursiveRef with $dynamicRef
  3. Vocabulary System: More modular vocabulary support
  4. Enhanced Conditionals: Better if/then/else evaluation tracking

Migration Example:

// Draft 7 approach
const draft7Schema = {
  type: "object", 
  properties: {
    name: { type: "string" }
  },
  dependencies: {
    creditCard: ["billingAddress"]  // Dependencies as array
  }
};

// 2019-09 approach  
const draft2019Schema = {
  type: "object",
  properties: {
    name: { type: "string" }
  },
  dependentRequired: {
    creditCard: ["billingAddress"]  // More explicit dependent requirements
  },
  dependentSchemas: {
    creditCard: {
      properties: {
        billingAddress: {
          type: "object",
          properties: {
            street: { type: "string" },
            city: { type: "string" }
          }
        }
      }
    }
  }
};