colinhacks/zod
Summary
Zod is a TypeScript-first schema validation library that enables type-safe parsing and validation of data with zero dependencies and a concise API.
View Cached Full Text
Cached at: 08/30/26, 03:26 PM
colinhacks/zod
Source: https://github.com/colinhacks/zod
Zod
TypeScript-first schema validation with static type inference
by @colinhacks
Read the docs →
What is Zod?
Zod is a TypeScript-first validation library. Define a schema and parse some data with it. You’ll get back a strongly typed, validated result.
import * as z from "zod";
const User = z.object({
name: z.string(),
});
// some untrusted data...
const input = {
/* stuff */
};
// the parsed result is validated and type safe!
const data = User.parse(input);
// so you can use it with confidence :)
console.log(data.name);
Features
- Zero external dependencies
- Works in Node.js and all modern browsers
- Tiny:
2kbcore bundle (gzipped) - Immutable API: methods return a new instance
- Concise interface
- Works with TypeScript and plain JS
- Built-in JSON Schema conversion
- Extensive ecosystem
Installation
npm install zod
Basic usage
Before you can do anything else, you need to define a schema. For the purposes of this guide, we’ll use a simple object schema.
import * as z from "zod";
const Player = z.object({
username: z.string(),
xp: z.number(),
});
Parsing data
Given any Zod schema, use .parse to validate an input. If it’s valid, Zod returns a strongly-typed deep clone of the input.
Player.parse({ username: "billie", xp: 100 });
// => returns { username: "billie", xp: 100 }
Note — If your schema uses certain asynchronous APIs like async refinements or transforms, you’ll need to use the .parseAsync() method instead.
const schema = z.string().refine(async (val) => val.length <= 8);
await schema.parseAsync("hello");
// => "hello"
AOT compilation
For hot validation paths, z.compile(schema) returns a schema clone with an ahead-of-time compiled fast path. Valid inputs take the compiled path; invalid inputs fall back to the regular parser so error reporting stays identical.
Across a 55-schema benchmark the median speedup is 2.4x, and it scales with how much work the schema does per parse: a large array of objects is ~9x, a 20-key object ~9x, a nested object ~4.5x, while a bare z.string() gains nothing — compilation removes per-node dispatch and allocation, and a single typeof has none to remove.
const CompiledPlayer = z.compile(Player);
CompiledPlayer.parse({ username: "billie", xp: 100 });
To enable compilation globally for schemas constructed after import:
import "zod/compile"; // place before modules that define schemas
Things to know:
- Compilation uses
new Function. Global mode is automatically disabled whenz.config({ jitless: true })is set (e.g. CSP environments); callingz.compile()directly is an explicit opt-in. - Schemas with async refinements or transforms can’t be compiled, and neither can a few other constructs. That is not an error:
z.compile()hands the schema back unchanged and it keeps using the regular parser, exactly as global mode leaves it. Pass{ strict: true }to throwZodCompileAsyncError/ZodCompileUnsupportedErrorinstead. - On invalid input, refinements and transforms may run twice (fast path, then fallback).
- Deriving a new schema from a compiled one (
.refine(),.extend(), etc.) returns an uncompiled schema — compile the final schema.
See compile docs for details.
Handling errors
When validation fails, the .parse() method will throw a ZodError instance with granular information about the validation issues.
try {
Player.parse({ username: 42, xp: "100" });
} catch (err) {
if (err instanceof z.ZodError) {
err.issues;
/* [
{
expected: 'string',
code: 'invalid_type',
path: [ 'username' ],
message: 'Invalid input: expected string'
},
{
expected: 'number',
code: 'invalid_type',
path: [ 'xp' ],
message: 'Invalid input: expected number'
}
] */
}
}
To avoid a try/catch block, you can use the .safeParse() method to get back a plain result object containing either the successfully parsed data or a ZodError. The result type is a discriminated union, so you can handle both cases conveniently.
const result = Player.safeParse({ username: 42, xp: "100" });
if (!result.success) {
result.error; // ZodError instance
} else {
result.data; // { username: string; xp: number }
}
Note — If your schema uses certain asynchronous APIs like async refinements or transforms, you’ll need to use the .safeParseAsync() method instead.
const schema = z.string().refine(async (val) => val.length <= 8);
await schema.safeParseAsync("hello");
// => { success: true; data: "hello" }
Inferring types
Zod infers a static type from your schema definitions. You can extract this type with the z.infer<> utility and use it however you like.
const Player = z.object({
username: z.string(),
xp: z.number(),
});
// extract the inferred type
type Player = z.infer<typeof Player>;
// use it in your code
const player: Player = { username: "billie", xp: 100 };
In some cases, the input & output types of a schema can diverge. For instance, the .transform() API can convert the input from one type to another. In these cases, you can extract the input and output types independently:
const mySchema = z.string().transform((val) => val.length);
type MySchemaIn = z.input<typeof mySchema>;
// => string
type MySchemaOut = z.output<typeof mySchema>; // equivalent to z.infer<typeof mySchema>
// number
Similar Articles
Parse, Don't Validate – In a Language That Doesn't Want You To
A blog post exploring the 'parse, don't validate' principle in TypeScript, showing how to use branded types to preserve type information after parsing, despite TypeScript's structural typing making this less idiomatic than in languages like Elm or Haskell.
A type-safe, realtime collaborative Graph Database in a CRDT
Codemix open-sources @codemix/graph, a type-safe, CRDT-backed graph database with TypeScript-native schema validation and realtime offline-first sync via Yjs.
Zerostack – A Unix-inspired coding agent written in pure Rust
Zerostack is a Unix-inspired coding agent built entirely in Rust, designed to assist developers with code generation and automation.
Show HN: Typebase – A single-folder back end you write in TypeScript
Typebase is a TypeScript-based backend tool that simplifies server deployment by allowing developers to define schemas and actions in a single folder, with support for various frontend frameworks and cloud platforms.
@southpolesteve: Zod 4.5 comes with a massive drop in memory usage. If you are running in @Cloudflare Workers you should update!
Zod 4.5 implements method memoization to drastically reduce memory usage, achieving up to 9.8x less heap retention than previous versions.