Zod

Zod is a TypeScript-first schema declaration and validation library. You define a schema once, and Zod gives you two things from it: runtime validation (parse untrusted data and reject what doesn't match) and a static type (inferred automatically, so your compile-time types and runtime checks can never drift apart). It has become the de facto way to validate external data — API requests, form input, environment variables, third-party responses — in TypeScript applications.

The problem it solves is the gap between TypeScript's compile-time types and runtime reality. TypeScript types vanish at runtime; a value typed User from await res.json() is a lie until something actually checks it. Zod closes that gap: the schema validates at runtime and is the source of the type, so "the data matched the type" is a fact you enforced, not an assumption you made.

TL;DR

Quick Example

Define a schema, derive the type, and parse untrusted input into a typed value:

The schema is the single definition; the type and the runtime check both come from it.

Core Concepts

Parse, Don't Validate

Zod's model is parsing: you hand it unknown data and get back a typed, validated value (or an error). This is stronger than a boolean "is this valid?" check because the output is narrowed to the correct type and can apply defaults and transforms along the way. After parse, TypeScript knows the shape — you're not casting and hoping.

parse vs safeParse

safeParse is usually the better fit for handling user or network input, where invalid data is normal, not exceptional.

Type Inference: One Source of Truth

The reason Zod fits TypeScript so well is z.infer. You don't write an interface and a validator that can silently disagree — you write the schema and derive the type. Change the schema and the type changes with it. This eliminates a whole class of bugs where the runtime check and the compile-time type drift apart.

Where to Use Zod

Zod belongs at every trust boundary — the seam where data crosses from an untyped or untrusted source into your typed code:

Inside your own typed code, you don't need Zod — TypeScript already guarantees shapes. Reach for it precisely where those guarantees end.

Composing Schemas

Zod schemas are composable building blocks:

Transforms let a schema reshape data as it validates (parse a date string into a Date); refinements add custom rules with your own error messages.

Common Mistakes

Trusting res.json() as a Type

Using parse Where Failure Is Expected

Duplicating the Type and the Schema

Writing a separate interface User alongside a UserSchema invites drift — change one, forget the other. Define the schema and derive the type with z.infer; keep one source of truth.

FAQ

Why do I need Zod if I already use TypeScript?

Because TypeScript types are erased at runtime — they check your code at compile time but validate nothing about actual data. A value typed User from an API response is an unchecked assumption. Zod validates the data at runtime and infers the type from the same schema, so the type reflects a check you actually performed rather than a hope.

What's the difference between parse and safeParse?

parse returns the typed value or throws a ZodError; use it when failure is exceptional. safeParse returns a result object ({ success, data } or { success, error }) and never throws; use it at input boundaries where invalid data is expected and you want to branch on it — like returning a 400 or rendering form errors.

How does Zod give me types without me writing them?

Through z.infer<typeof schema>, which extracts the static TypeScript type the schema describes. You define the schema once; the type is derived from it automatically. This is the core benefit — no separate interface to keep in sync, so the runtime check and the compile-time type can't drift.

Where should I actually use Zod?

At trust boundaries — where data enters your typed code from an untyped or untrusted source: API request bodies, third-party and API responses, form input, environment variables, URL params, and LLM structured output. Inside your own already-typed code you don't need it; TypeScript covers that.

Is Zod only for TypeScript?

It works in plain JavaScript too — the runtime validation is fully useful without types. But its signature feature, type inference from schemas, pays off most in TypeScript, which is where it's most popular. In JS you get robust runtime validation; in TS you also get the types for free.

Related Topics

References