Knowledge base from the Zod (TypeScript-first schema validation) documentation, covering Zod 4 core API, Zod Mini, Zod Core internals, JSON Schema conversion, codecs, error customization, and the Zod 3→4 migration guide. Use when defining or refining Zod schemas, choosing between Zod and Zod Mini, converting schemas to/from JSON Schema, customizing validation errors, building bidirectional codecs, or migrating a Zod 3 codebase to Zod 4.
Package: zod (v4) | Chapters: 61 | Generated: 2026-08-24
discriminated unions, codecs, z.record, JSON Schema, or another indexed topic; I find and read the relevant chapter.ch025; I load that specific chapter.When you ask about something not covered in Core Patterns, I will read the relevant chapter file before answering.
Zod maps schemas one-to-one to TypeScript types: define a schema, derive its type with z.infer<typeof schema>, and validate untrusted input with .parse()/.safeParse(). The API is immutable — every modifier method (.optional(), .min(), .refine(), ...) returns a new schema instance rather than mutating the original.
Absence has four flavors: .optional() (allows undefined), .nullable() (allows null), .nullish() (both), .exactOptional() (key may be absent, but not explicitly undefined — matches exactOptionalPropertyTypes). Fallback values have three flavors too: .default(value) short-circuits on undefined input (value must match the output type), .prefault(value) substitutes on undefined but still runs the full pipeline (value must match the input type), and .catch(value) recovers from any validation failure, not just missing input.
Objects strip unknown keys by default. Use z.strictObject() to reject them, z.looseObject() to pass them through, or .catchall(schema) to validate them. Prefer object spread ({ ...A.shape, ...B.shape }) over chained .extend() when merging schemas — it's faster to type-check and behaves identically in Zod and Zod Mini. .safeExtend() is the refinement-safe version of .extend() (plain .extend() throws on schemas with .refine()).
Unions: z.union([...]) checks options in order and returns the first match. z.discriminatedUnion(key, [...]) is strictly better whenever every option is an object sharing one literal-valued key — faster and gives better errors. z.xor([...]) requires exactly one match (watch for accidental overlap between loosely-typed object options — use .strict() on the narrower one).
Transforms vs. codecs: .transform(fn)/z.transform(fn) is a one-way reshape — it makes .encode() throw anywhere it appears in a schema. z.codec(inputSchema, outputSchema, { decode, encode }) is the bidirectional alternative — use it whenever a value needs to go both directions (e.g. ISO string ↔ Date at a network boundary). Inside a transform/codec, report failure via ctx.issues.push(...) + return z.NEVER, never throw.
Refinements (.refine()) add pass/fail validation without ever changing the inferred type. They're continuable by default (all failing refinements collect into .issues); pass abort: true to stop at the first failure, and path: [...] to attach a cross-field error to a specific key (e.g. a "confirm password" mismatch).
Error customization is a five-level precedence chain, highest to lowest: check-level → schema-level ({ error: "..." } or a function) → per-parse (.parse(x, { error })) → global (z.config({ customError })) → locale (z.config(en())). Error-map functions receive the full issue (code, input, path, schema for reading .meta()) and can return undefined to defer to the next layer.
Metadata lives in registries. .meta({...}) is shorthand for registering in z.globalRegistry; metadata is tied to the exact schema instance (derived schemas from .refine()/.extend() don't inherit it) and flows directly into z.toJSONSchema() output, where it can override generated keywords.
Two packages, one core. zod (method-chained, most ergonomic, default choice) and zod/mini (function-based, tree-shakable, ~60-70% smaller bundles) both implement zod/v4/core. Library code that must support both should depend only on "zod/v4/core" types — never "zod/v4" or "zod/v4/mini" directly.
Coming from Zod 3? The biggest behavior changes: .default() now short-circuits instead of re-parsing (use the new .prefault() for old behavior), defaults now apply inside optional object fields, z.record() requires two arguments and is exhaustive by default on enum keys (z.partialRecord() for the old partial behavior), and string formats moved to top-level functions (z.email() instead of z.string().email()).
| # | Title | Key Concepts |
|---|---|---|
| ch001 | Introduction & Installation | schema-first validation, immutable API, tsconfig strict |
| ch034 | Basic Usage — Define, Parse, Handle Errors, Infer | .parse, .safeParse, z.infer, z.input/z.output |
| ch035 | Matching an Existing Type | z.toZod<T>(), exact type equality |
| # | Title | Key Concepts |
|---|---|---|
| ch002 | Primitives & Coercion | z.string/number/boolean, z.coerce.* |
| ch003 | Literals | z.literal, multi-value literals |
| ch004 | Strings — Validation & Transforms | .min/.max/.regex, .trim/.toLowerCase |
| ch005 | String Formats — Identifiers, URLs & Contact Info | z.email, z.uuid, z.url, z.e164, z.jwt |
| ch006 | String Formats — ISO Dates, Network & Hashes | z.iso.datetime, z.ipv4, z.hash, z.stringFormat |
| ch007 | Template Literals | z.templateLiteral |
| ch008 | Numbers | z.number, .gt/.lt/.multipleOf, z.nan |
| ch009 | Integers, BigInts & Booleans | z.int, z.int32, z.bigint, z.boolean |
| ch010 | Dates | z.date, .min/.max |
| ch011 | Enums | z.enum, .exclude/.extract |
| ch012 | Stringbools | z.stringbool |
| # | Title | Key Concepts |
|---|---|---|
| ch013 | Optional, Exact Optional, Nullable & Nullish | .optional, .exactOptional, .nullable, .nullish |
| ch014 | Unknown, Any & Never | z.any, z.unknown, z.never |
| ch015 | Objects — Definition, Strictness & Shape | z.object, z.strictObject, .catchall, .keyof |
| ch016 | Objects — Extending & Deriving | .extend, .safeExtend, .pick/.omit, .partial |
| ch017 | Recursive Objects | getter-based recursion, mutual recursion |
| ch018 | Arrays & Tuples | z.array, z.tuple, variadic rest |
| ch019 | Unions & Exclusive Unions (XOR) | z.union, z.xor |
| ch020 | Discriminated Unions & Intersections | z.discriminatedUnion, z.intersection |
| ch021 | Records | z.record, z.partialRecord, z.looseRecord |
| ch022 | Maps & Sets | z.map, z.set |
| ch023 | Files | z.file, .mime |
| ch024 | Instanceof | z.instanceof, z.property |
| ch031 | JSON | z.json, recursive union |
| ch032 | Functions | z.function, .implement |
| ch033 | Custom & Apply | z.custom, .apply |
| # | Title | Key Concepts |
|---|---|---|
| ch025 | Refinements | .refine, abort, path |
| ch026 | Codecs — Basics | z.codec, decode/encode |
| ch027 | Pipes | .pipe, z.input/z.output |
| ch028 | Transforms & Preprocess | z.transform, z.preprocess, ctx.issues |
| ch029 | Defaults, Prefaults & Catch | .default, .prefault, .catch |
| ch030 | Branded Types & Readonly | .brand, .readonly |
| # | Title | Key Concepts |
|---|---|---|
| ch036 | Codecs — Encode/Decode Mechanics | z.invertCodec, type-safe inputs, async/safe variants |
| ch037 | How Encoding Interacts With Other Schema Features | refinements, defaults, catch, stringbool, transforms |
| ch038 | Useful Codecs Reference | stringToNumber, isoDatetimeToDate, jsonCodec, base64/hex↔bytes |
| # | Title | Key Concepts |
|---|---|---|
| ch039 | AOT Compilation | z.compile, import "zod/compile" |
| # | Title | Key Concepts |
|---|---|---|
| ch040 | Ecosystem & Community Resources | tRPC, React Hook Form, zshy |
| # | Title | Key Concepts |
|---|---|---|
| ch041 | The error Param & Schema-Level Customization | error param, error map, iss.schema |
| ch042 | Global Error Customization, Internationalization & Precedence | z.config, locales, precedence chain |
| ch043 | Per-Parse Error Customization | .parse options, reportInput |
| ch044 | Formatting Errors | z.treeifyError, z.prettifyError, z.flattenError |
| # | Title | Key Concepts |
|---|---|---|
| ch045 | JSON Schema — Conversion Functions | z.toJSONSchema, z.fromJSONSchema, unrepresentable |
| ch046 | JSON Schema — Type-by-Type Conversion Details | format, pattern, additionalProperties |
| ch047 | JSON Schema — Registries & Multi-Schema Output | z.globalRegistry, $ref |
| # | Title | Key Concepts |
|---|---|---|
| ch048 | For Library Authors — Peer Dependencies & Subpaths | Standard Schema, zod/v4/core |
| ch049 | For Library Authors — Accepting User-Defined Schemas | generic constraints, z4.parse |
| ch050 | Metadata & Registries | z.registry, .register, .meta, .describe |
| ch051 | Zod Core — Schema Classes & Internals | $ZodType, _zod.def |
| ch052 | Zod Core — Checks, Errors & Issues | $ZodCheck, $ZodError, $ZodIssue |
| ch053 | Zod Mini — Overview & When to Use It | tree-shaking, bundle size |
| ch054 | Zod Mini — API Reference | .check(), check function catalog |
| ch055 | The Zod Package — Method Overview | ZodType methods |
| # | Title | Key Concepts |
|---|---|---|
| ch056 | Migration — Number, String, Coercion & Defaults | .prefault, coercion input type |
| ch057 | Migration — Objects, Enums, Arrays, Functions & Refine | defaults in optional fields, z.function factory |
| ch058 | Migration — Refine, Record & Intersection Changes | ctx.path removal, z.record arity |
| ch059 | Migration — Internal & Architectural Changes | generics, _zod.def, ZodEffects removal |
| # | Title | Key Concepts |
|---|---|---|
| ch060 | Zod 4 Release Notes — Performance & Rationale | benchmarks, tsc instantiations, bundle size |
| ch061 | Versioning Policy | subpath versioning, peer dependencies |
This skill covers the Zod v4 documentation (zod.dev/llms-full.txt, fetched 2026-08-23) — the schema API, Zod Mini, Zod Core internals, JSON Schema conversion, codecs, error customization, and the Zod 3→4 migration guide. It does not cover Zod 3-specific APIs beyond what's documented in the migration guide, nor third-party ecosystem library internals (tRPC, React Hook Form, etc.) beyond what's mentioned in the Ecosystem chapter. For implementation details specific to your codebase, combine with project-specific tools.