ajv and json-schema-to-ts both work with JSON Schema but serve fundamentally different purposes in the frontend development workflow. ajv is a high-performance runtime validator that checks if JavaScript objects conform to a given JSON Schema, throwing errors or returning boolean results at execution time. json-schema-to-ts, on the other hand, is a build-time tool that converts JSON Schema definitions into accurate TypeScript types, enabling static type checking during development without any runtime overhead. While they can be used together, they solve distinct problems: one ensures data correctness when your app runs, the other ensures type safety while you write code.
Both ajv and json-schema-to-ts help developers work with JSON Schema in TypeScript projects, but they operate at completely different stages of the development lifecycle and solve different problems. Confusing them is common โ one validates data while your app runs, the other generates types while you write code. Letโs clarify when and how to use each.
ajv is a runtime validator. It takes a JSON Schema and an actual JavaScript object, then checks whether the object matches the schema. If not, it tells you why โ useful for handling real-world data that might not match expectations.
import Ajv from 'ajv';
const ajv = new Ajv();
const schema = {
type: 'object',
properties: { name: { type: 'string' }, age: { type: 'number' } },
required: ['name']
};
const validate = ajv.compile(schema);
const valid = validate({ name: 'Alice', age: 30 });
console.log(valid); // true
const invalid = validate({ age: 'thirty' });
console.log(invalid); // false
console.log(validate.errors); // detailed error info
json-schema-to-ts is a type generator. It reads a JSON Schema (usually as a const assertion in TypeScript) and produces a corresponding TypeScript type. No validation happens at runtime โ itโs purely for static analysis during development.
import { FromSchema } from 'json-schema-to-ts';
const userSchema = {
type: 'object',
properties: { name: { type: 'string' }, age: { type: 'number' } },
required: ['name']
} as const;
type User = FromSchema<typeof userSchema>;
// User is now equivalent to: { name: string; age?: number }
// This gives a TypeScript error at compile time:
const badUser: User = { age: 'thirty' }; // โ Property 'name' is missing
Youโre calling an external REST API that returns user data. You donโt control the response format, and it might change unexpectedly.
ajv: Because you need to verify the shape of incoming data at runtime before using it in your app. TypeScript types alone wonโt protect you if the server sends malformed JSON.// Runtime check with ajv
if (!validate(response)) {
throw new Error(`Invalid API response: ${ajv.errorsText(validate.errors)}`);
}
// Safe to use response.name, etc.
json-schema-to-ts: Even if you generate a User type, the actual response might not match it. Youโd get no runtime protection.Your team defines all data contracts using JSON Schema files. Frontend and backend share these schemas, and you want TypeScript interfaces auto-generated from them.
json-schema-to-ts: To avoid manually writing and maintaining duplicate TypeScript interfaces. Changes to the schema automatically update your types.// Shared schema โ auto-generated type
const apiResponseSchema = { /* ... */ } as const;
type ApiResponse = FromSchema<typeof apiResponseSchema>;
ajv: If you still want to validate data at service boundaries (e.g., validating requests entering your backend), use both tools together.Yes โ and often should be. A common pattern in professional apps:
json-schema-to-ts to generate TypeScript types from your canonical JSON Schemas.ajv to validate actual runtime data against those same schemas.This gives you both compile-time type safety and runtime validation.
import Ajv from 'ajv';
import { FromSchema } from 'json-schema-to-ts';
const userSchema = {
type: 'object',
properties: { id: { type: 'number' }, email: { type: 'string', format: 'email' } },
required: ['id', 'email']
} as const;
type User = FromSchema<typeof userSchema>;
// Compile-time: TypeScript enforces correct structure
const newUser: User = { id: 1, email: 'test@example.com' };
// Runtime: ajv validates actual data (e.g., from fetch)
const ajv = new Ajv({ strict: false });
const validate = ajv.compile(userSchema);
fetch('/api/user')
.then(res => res.json())
.then(data => {
if (!validate(data)) {
console.error('Invalid user data:', validate.errors);
return;
}
// Now safe to treat `data` as User
processUser(data);
});
ajv provides detailed, customizable error messages. You can even add your own keywords or formats (like format: 'uuid'). This is critical for debugging production issues or giving users meaningful form feedback.
// Custom format support in ajv
ajv.addFormat('uuid', /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
json-schema-to-ts has no runtime behavior, so thereโs nothing to โhandleโ at runtime. Its DX benefit is catching mismatches before you run the code. For example, if you forget a required field, TypeScript fails the build.
ajv adds to your bundle size because it includes a full validation engine. However, it supports tree-shaking and standalone code generation to minimize this.json-schema-to-ts adds zero runtime cost. The entire package is dev-only; its output is pure TypeScript types that vanish after compilation.If youโre building a lightweight frontend where every KB counts and you fully trust your data sources, json-schema-to-ts alone may suffice. But if you handle untrusted input (user forms, third-party APIs), skipping runtime validation is risky.
As of the latest official documentation:
ajv is actively maintained, with stable support for JSON Schema Draft 7, 2019-09, and 2020-12 via plugins.json-schema-to-ts is also actively maintained and compatible with modern TypeScript versions. It correctly handles complex schema constructs like oneOf, anyOf, and recursive references.Neither package is deprecated.
ajvjson-schema-to-tsDonโt treat them as competitors โ theyโre complementary tools in a mature frontend architecture. One guards your runtime, the other sharpens your development experience.
Choose ajv when you need to validate dynamic or external data (like API responses, user input, or config files) at runtime to prevent invalid data from breaking your application. Itโs essential for enforcing contracts where type safety alone isnโt enough โ for example, when consuming third-party APIs or handling form submissions. Its extensive support for JSON Schema Draft 7 and newer, plus powerful features like custom keywords and error reporting, makes it the go-to for robust validation logic.
Choose json-schema-to-ts when your team maintains JSON Schemas as the source of truth for data structures and wants those schemas to automatically generate precise TypeScript interfaces. This eliminates manual type duplication and ensures your TypeScript code stays in sync with your schema definitions. Itโs ideal for internal APIs or systems where schema-first design is practiced, and you want compile-time guarantees without runtime performance costs.
ย
The fastest JSON validator for Node.js and browser.
Supports JSON Schema draft-04/06/07/2019-09/2020-12 (draft-04 support requires ajv-draft-04 package) and JSON Type Definition RFC8927.
More than 100 people contributed to Ajv, and we would love to have you join the development. We welcome implementing new features that will benefit many users and ideas to improve our documentation.
Please review Contributing guidelines and Code components.
All documentation is available on the Ajv website.
Some useful site links:
Since I asked to support Ajv development 40 people and 6 organizations contributed via GitHub and OpenCollective - this support helped receiving the MOSS grant!
Your continuing support is very important - the funds will be used to develop and maintain Ajv once the next major version is released.
Please sponsor Ajv via:
Thank you.
Ajv generates code to turn JSON Schemas into super-fast validation functions that are efficient for v8 optimization.
Currently Ajv is the fastest and the most standard compliant validator according to these benchmarks:
Performance of different validators by json-schema-benchmark:
addSchema or compiled to be available)type keywordsTo install version 8:
npm install ajv
Try it in the Node.js REPL: https://runkit.com/npm/ajv
In JavaScript:
// or ESM/TypeScript import
import Ajv from "ajv"
// Node.js require:
const Ajv = require("ajv")
const ajv = new Ajv() // options can be passed, e.g. {allErrors: true}
const schema = {
type: "object",
properties: {
foo: {type: "integer"},
bar: {type: "string"},
},
required: ["foo"],
additionalProperties: false,
}
const data = {
foo: 1,
bar: "abc",
}
const validate = ajv.compile(schema)
const valid = validate(data)
if (!valid) console.log(validate.errors)
Learn how to use Ajv and see more examples in the Guide: getting started
See https://github.com/ajv-validator/ajv/releases
Please note: Changes in version 8.0.0
Please review and follow the Code of conduct.
Please report any unacceptable behaviour to ajv.validator@gmail.com - it will be reviewed by the project team.
To report a security vulnerability, please use the Tidelift security contact. Tidelift will coordinate the fix and disclosure. Please do NOT report security vulnerabilities via GitHub issues.
Ajv is a part of Tidelift subscription - it provides a centralised support to open-source software users, in addition to the support provided by software maintainers.