Validate.js
a tiny vanilla javascript validation library
Install / Use
/learn @jakelazaroff/Validate.jsREADME
validate.js
2kb vanilla JavaScript validation library with TypeScript and Standard Schema support.
Why validate.js?
The JavaScript validation library field is crowded. Why use validate.js over Valibot or Zod?
validate.js is vanilla JavaScript — drop this file in any JavaScript or TypeScript project and it will Just Work regardless of toolchain. You might use it if you're building a website without a bundler, if you're not using TypeScript or if you just want something small and vanilla.
Why not use validate.js? If you're building a Real Production Application, you probably already have package.json set up with a bundler, in which case you may as well use one of the larger libraries (as long as they tree shake to a small bundle size).
Installing
validate.js is not on npm; instead, it's meant to be vendored, or copied directly into your project's source code.
Don't be put off — validate.js a single 350 line file, of which only 150 lines are actually JavaScript code. It doesn't bite!
Examples
Easily validate complex types by using simple validators together:
import { parse, object, number, string } from "./validate.js";
const schema = object({
a: string,
b: number
});
const result = parse(schema, { a: "abc", b: 123 });
If you're using TypeScript, validate.js is even more useful, statically narrowing the types of parsed objects:
import { parse, object, number, string } from "./validate.js";
const schema = object({
a: string,
b: number
});
const foo: unknown = { a: "abc", b: 123 };
const result = parse(schema, foo);
result; // { a: string; b: number }
In fact, validate.js can do this even if you're using vanilla JavaScript! You can express almost the entire TypeScript type system in JSDoc comments, which means you can get the benefits of static type checking in normal JavaScript files. (That's how validate.js provides TypeScript support.)
import { parse, object, number, string } from "./validate.js";
const schema = object({
a: string,
b: number
});
/** @type {unknown} */
const foo = { a: "abc", b: 123 };
const result = parse(schema, foo);
result; // { a: string; b: number }
validate.js conforms to Standard Schema, so you can use it anywhere you'd use another conformant validation library.
API
parse(schema, value)
Validates a value against a schema. Returns the value on success, throws a SchemaError on failure.
import { parse, string } from "./validate.js";
parse(string, "hello"); // "hello"
parse(string, 42); // throws SchemaError
is(schema, value)
Validates a value against a schema. Returns true or false.
import { is, string } from "./validate.js";
is(string, "hello"); // true
is(string, 42); // false
Primitive Schemata
boolean
Matches booleans.
import { is, boolean } from "./validate.js";
is(boolean, false); // true
is(boolean, 0); // false
number
Matches numbers.
import { is, number } from "./validate.js";
is(number, 0); // true
is(number, "string"); // false
string
Matches strings.
import { is, string } from "./validate.js";
is(string, "test"); // true
is(string, true); // false
bigint
Matches bigints.
import { is, bigint } from "./validate.js";
is(bigint, 1n); // true
is(bigint, 1); // false
symbol
Matches symbols.
import { is, symbol } from "./validate.js";
is(symbol, Symbol()); // true
is(symbol, "string"); // false
undefined
Matches undefined.
import { is, undefined as undef } from "./validate.js";
is(undef, undefined); // true
is(undef, null); // false
null
Matches null.
import { is, null as nil } from "./validate.js";
is(nil, null); // true
is(nil, undefined); // false
any
Matches any value.
import { is, any } from "./validate.js";
is(any, "anything"); // true
literal(value)
Matches a specific value using strict equality.
import { is, literal } from "./validate.js";
const schema = literal(5);
is(schema, 5); // true
is(schema, 6); // false
Complex Schemas
object(shape)
Validates that a value is an object where each property matches the corresponding schema.
import { parse, object, number, string } from "./validate.js";
const schema = object({
name: string,
age: number
});
parse(schema, { name: "jake", age: 34 }); // { name: string; age: number }
parse(schema, { name: 34 }); // throws
record(schema)
Validates that all values in an object match the given schema.
import { parse, record, number } from "./validate.js";
const schema = record(number);
parse(schema, { a: 1, b: 2 }); // { [key: PropertyKey]: number }
parse(schema, { a: "one" }); // throws
array(schema)
Validates that all elements in an array match the given schema.
import { parse, array, number } from "./validate.js";
const schema = array(number);
parse(schema, [1, 2, 3]); // number[]
parse(schema, [1, "two"]); // throws
instance(constructor)
Validates that a value is an instance of the given constructor.
import { is, instance } from "./validate.js";
const schema = instance(Date);
is(schema, new Date()); // true
is(schema, {}); // false
Combinators
union(...schemata)
Matches if the value matches any of the given schemata. Narrows to a union type.
import { parse, union, number, string } from "./validate.js";
const schema = union(number, string);
parse(schema, 0); // number | string
parse(schema, "one"); // number | string
parse(schema, false); // throws
intersect(...schemata)
Matches if the value matches all of the given schemata. Narrows to an intersection type.
import { parse, intersect, object, number, string } from "./validate.js";
const schema = intersect(
object({ a: number }),
object({ b: string })
);
parse(schema, { a: 1, b: "2" }); // { a: number } & { b: string }
parse(schema, { a: 1 }); // throws
optional(schema)
Matches if the value matches the given schema or is undefined.
import { parse, optional, number } from "./validate.js";
const schema = optional(number);
parse(schema, 0); // number | undefined
parse(schema, undefined); // number | undefined
parse(schema, "string"); // throws
nullable(schema)
Matches if the value matches the given schema or is null.
import { parse, nullable, number } from "./validate.js";
const schema = nullable(number);
parse(schema, 0); // number | null
parse(schema, null); // number | null
parse(schema, "string"); // throws
custom(predicate, errorMessage)
Creates a schema from a type predicate and an error message function.
import { is, custom } from "./validate.js";
const email = custom(
(x): x is `${string}@${string}` =>
typeof x === "string" && x.includes("@"),
(x) => `Expected email, received \`${JSON.stringify(x)}\``
);
is(email, "user@example.com"); // true
is(email, "not-an-email"); // false
InferOutput
TypeScript utility type that extracts the output type from a schema.
import { object, number, string, InferOutput } from "./validate.js";
const schema = object({
name: string,
age: number
});
type Person = InferOutput<typeof schema>; // { name: string; age: number }
