About zod
Zod is a TypeScript-first schema validation library for developers who need runtime validation and static type inference from the same schema. It offers parsing, refinement, transformation, and composable schema definitions without external dependencies.
Key features
- 01Runtime validation and TypeScript type inference
- 02Composable object, array, tuple, and union schemas
- 03Refinements and data transformations
- 04Synchronous and asynchronous parsing
- 05Detailed validation errors
Use cases
- 01Validating API payloads at application boundaries
- 02Checking environment variables and untrusted input
- 03Defining form schemas with inferred types
- 04Transforming and validating parsed data
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ enderpuentes/ ai-agent-skills --skill zodAfter installing, type/zodin Claude Code to confirm it loaded.
Bundled filesLICENSE.mdreference.md
Details
From the project READMEZod
Overview
Zod is a TypeScript-first schema validation library with static type inference. Define a schema once; you get both runtime validation and a TypeScript type (via z.infer). Zero external dependencies; works in Node and browsers. Ideal for forms (e.g. with react-hook-form), API parsing, env vars, and any untrusted input.
Requirements: TypeScript 5.5+ recommended; enable strict in tsconfig.json.
Install: Add zod via your package manager. See zod.dev.
Quick start
import { z } from "zod";
const User = z.object({
name: z.string(),
age: z.number().optional(),
});
type User = z.infer<typeof User>;
// { name: string; age?: number }
const data = User.parse(input); // throws ZodError if invalid
const result = User.safeParse(input); // { success: true, data } | { success: false, error }
Primitives and common types
| Schema | Type | Notes |
|---|---|---|
z.string() | string | |
z.number() | number | |
z.boolean() | boolean | |
z.bigint() | bigint | |
z.date() | Date | |
z.undefined() | undefined | |
z.null() | null | |
z.void() | void | |
z.any() | any | |
z.unknown() | unknown | |
z.never() | never | |
z.literal("x") | literal | |
z.enum(["a", "b"]) | union of literals | |
z.string().email() | string | email format |
z.string().url() | string | URL |
z.string().uuid() | string | UUID |
z.string().datetime() | string | ISO datetime |
z.number().int() | number | integer |
z.number().min(n).max(m) | number | range |
z.boolean() / z.string().transform(...) | stringbool | "true"/"false" coercion |
Optional: .optional() → T | undefined. Nullable: .nullable() → T | null. Nullish: .nullish() → T | null | undefined. Default: .default(value).
Objects
const Schema = z.object({
name: z.string(),
age: z.number().optional(),
tags: z.array(z.string()).default([]),
});
type Schema = z.infer<typeof Schema>;
- .shape:
Schema.shape.name(access field schema). - .keyof():
Schema.keyof()→ enum of keys. - .extend({ ... }): Add or override keys.
- .pick({ name }) / .omit({ age }): Subset of keys.
- .partial() / .required({ name }): Optionalize or require.
- .strict(): No extra keys (default in z.object). z.strictObject / z.looseObject for behavior variants.
- .catchall(z.string()): Allow extra keys with a schema.
- Nested:
z.object({ user: z.object({ name: z.string() }) }). - Recursive:
z.lazy(() => Category)for self-referential structures.
Arrays and tuples
- Arrays:
z.array(z.string()),z.string().array(). - Tuples:
z.tuple([z.string(), z.number()])— fixed length and types. - Non-empty:
.min(1)or dedicated helpers if available.
Unions and intersections
- Union:
z.union([z.string(), z.number()])orz.string().or(z.number()). - Discriminated union: Use a common key (e.g.
type: "a") andz.discriminatedUnion("type", [z.object({ type: z.literal("a"), ... }), ...]). - Intersection:
z.intersection(A, B)orA.and(B).
Refinements and transform
- .refine(fn, message?): Custom validation; keep type unchanged.
- .superRefine: Multiple issues or async; push to
ctx. - .transform(fn): Change output type. Input and output can differ; use
z.input<typeof schema>andz.output<typeof schema>(orz.inferfor output). - .pipe(otherSchema): Chain validation/transform (e.g. string → number via
z.string().pipe(z.coerce.number())).
Parsing and errors
- .parse(input): Returns data or throws ZodError.
- .safeParse(input): Returns
{ success: true, data }or{ success: false, error: ZodError }. - ZodError:
error.issues(array of{ path, message, code }),error.format()for nested shape. - Async:
.parseAsync/.safeParseAsyncfor schemas with async refinements or transforms.
Type inference
- z.infer: Output type (after transforms/defaults).
- z.input: Input type (before transforms; useful when input ≠ output).
- z.output: Same as
z.inferfor output type.
const S = z.string().transform((s) => s.length);
type In = z.input<typeof S>; // string
type Out = z.output<typeof S>; // number
Integration: React Hook Form
Use @hookform/resolvers with zodResolver:
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { z } from "zod";
const formSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
type FormValues = z.infer<typeof formSchema>;
const form = useForm<FormValues>({
resolver: zodResolver(formSchema),
defaultValues: { email: "", password: "" },
});
Best practices
- Prefer strict schemas (no extra keys) for API boundaries; use .passthrough() only when you need to forward unknown keys.
- Use .default() for optional fields with a default value.
- For API/env parsing, use safeParse and handle errors; show user-friendly messages from
error.issues. - Use discriminated unions for variant payloads (e.g. events by
type). - Coerce only when safe:
z.coerce.number(),z.coerce.boolean(), or custom.transform().
Common mistakes
- Forgetting strict: Keep TypeScript
strict: true; Zod works best with it. - Input vs output: After
.transform(), usez.input<>/z.output<>if the type seen by callers differs. - parse in hot path: Prefer validating once at boundaries (e.g. API handler, form submit) rather than on every render.
- Overly broad schema: Prefer specific types (e.g.
.email(),.min()) instead of plainz.string()when the domain has rules.
Additional resources
- reference.md — Official Zod docs links, API sections (primitives, objects, strings, numbers, refinements, etc.), Zod Mini, ecosystem.
- Official: https://zod.dev — Introduction, API, basics, ecosystem.
- API (Zod 4): https://zod.dev/api — Full schema types and methods.
- LLMs / index: https://zod.dev/llms.txt — Structured doc for tools/agents.