4. Parsing, Error Formatting, Registries, JSON Schema & Static Types
Beyond schema construction, Zod v4 provides standalone and method-based execution engines (parse, safeParse, validate, encode, decode), a streamlined 11-member $ZodIssue discriminated union with built-in formatters (prettifyError, treeifyError, flattenError, formatError), strongly-typed WeakMap metadata registries ($ZodRegistry, globalRegistry), bidirectional JSON Schema conversion (toJSONSchema, fromJSONSchema), and static/runtime input-output projection utilities (z.infer, z.input, z.output).
Source Code
from drawlib import canvas
from drawlib.diagrams.architecture import ArchitectureDiagram, Node, NodeGroup, PhosphorIcon
from drawlib.styles import Styles
canvas.clear()
canvas.setup(width=188, height=96, dpi=150)
d = ArchitectureDiagram(
node_style=Styles.Primary,
node_text_style=Styles.DarkBold.patch(text_size=10.0),
edge_style=Styles.DarkBold,
edge_text_style=Styles.Dark.patch(text_size=10.0),
node_card_style=Styles.Neutral,
title="Zod v4 Execution, Error Formatting, Registry & JSON Schema Surface",
)
# Left Group: Parse & Codec Execution (node width=46 -> center x = 5 + 23 = 28)
exec_grp = d.add(
NodeGroup(title="1. Parse & Codec Execution", padding=5.0),
xy=(0.0, 0.0),
)
parse_node = exec_grp.add(
Node("Forward Parse & Guard\nparse / safeParse\nparseAsync / validate", width=46, height=20, icon=PhosphorIcon.PLAY_CIRCLE, icon_size=6.5, card_style=Styles.PrimaryNeutral),
xy=(28.0, 52.0),
)
codec_exec = exec_grp.add(
Node("Bidirectional Codec API\ndecode / encode\nsafeDecode / safeEncode", width=46, height=20, icon=PhosphorIcon.ARROWS_LEFT_RIGHT, icon_size=6.5, card_style=Styles.Neutral),
xy=(28.0, 15.0),
)
# Center Group: Core Schema & Error Engine (node width=40 -> center x = 5 + 20 = 25)
core_grp = d.add(
NodeGroup(title="2. Core Schema & $ZodError", padding=5.0),
xy=(66.0, 0.0),
)
schema_hub = core_grp.add(
Node("ZodType<O, I>\n_zod.run(payload, ctx)\nz.infer / z.input / z.output", width=40, height=20, icon=PhosphorIcon.CUBE, icon_size=6.5, style=Styles.WhiteBold, card_style=Styles.PrimaryFlat, text_style=Styles.WhiteBold.patch(text_size=10.0)),
xy=(25.0, 52.0),
)
err_hub = core_grp.add(
Node("ZodError & Formatters\nprettifyError / treeifyError\nflattenError / formatError", width=40, height=20, icon=PhosphorIcon.WARNING_OCTAGON, icon_size=6.5, style=Styles.WhiteBold, card_style=Styles.AccentFlat, text_style=Styles.WhiteBold.patch(text_size=10.0)),
xy=(25.0, 15.0),
)
# Right Group: Registries & JSON Schema (node width=46 -> center x = 5 + 23 = 28)
meta_grp = d.add(
NodeGroup(title="3. Registries & JSON Schema", padding=5.0),
xy=(126.0, 0.0),
)
reg_node = meta_grp.add(
Node("Metadata Registries\n$ZodRegistry<Meta>\nz.globalRegistry / .meta()", width=46, height=20, icon=PhosphorIcon.BOOKMARK_SIMPLE, icon_size=6.5, card_style=Styles.Neutral),
xy=(28.0, 52.0),
)
json_node = meta_grp.add(
Node("JSON Schema Bridge\nz.toJSONSchema(schema)\nz.fromJSONSchema(json)", width=46, height=20, icon=PhosphorIcon.FILE_CODE, icon_size=6.5, card_style=Styles.PrimaryNeutral),
xy=(28.0, 15.0),
)
# Connections
d.connect(parse_node, schema_hub, padding=1.5)
d.connect(codec_exec, schema_hub, padding=1.5)
d.connect(schema_hub, err_hub, label="issues[]", padding=1.5)
schema_hub.fork([reg_node, json_node], at_x=119.0, padding=1.5)
d.connect(reg_node, json_node, label="metadata", padding=1.5)
d.draw(xy=(94.0, 46.0), align="center")
canvas.save()
functionz.parse / z.safeParse / z.parseAsync / z.safeParseAsync#
Zod v4 exposes both standalone functions (z.parse(schema, data), z.safeParse(schema, data), z.validate(schema, data)) and instance methods (schema.parse(data), schema.safeParse(data), schema.validate(data)).
Parse & Type-Guard Execution Signatures#
| Function / Method | Return Type | Throws on Invalid? | Description |
|---|---|---|---|
z.parse(schema, value, ctx?) / schema.parse(value, ctx?) |
z.output<typeof schema> |
Yes (ZodError) |
Synchronously validates value in forward direction. Throws $ZodAsyncError if any schema or check returns a Promise. |
z.safeParse(schema, value, ctx?) / schema.safeParse(value, ctx?) |
SafeParseResult<z.output<typeof schema>> |
No (throws only on async) | Returns { success: true, data: O } | { success: false, error: ZodError<I> }. The error property is a lazy getter that only finalizes issues on first read. |
z.parseAsync(schema, value, ctx?) / schema.parseAsync(value, ctx?) |
Promise<z.output<typeof schema>> |
Yes (rejects with ZodError) |
Asynchronously validates value, awaiting any async refinements or transforms. |
z.safeParseAsync(schema, value, ctx?) / schema.safeParseAsync(value, ctx?) / schema.spa(value, ctx?) |
Promise<SafeParseResult<z.output<typeof schema>>> |
No | Asynchronous counterpart to safeParse. .spa is a zero-overhead prototype alias on ZodType. |
z.validate(schema, value, ctx?) / schema.validate(value, ctx?) |
value is z.input<typeof schema> (boolean) |
No (throws only on async) | High-speed boolean type-guard (abortEarly: true, skips output allocation and ZodError instantiation; uses compiled validator fast path when available). |
z.validateAsync(schema, value, ctx?) / schema.validateAsync(value, ctx?) |
Promise<boolean> |
No | Asynchronous boolean validation (abortEarly: true). |
ParseContext Options (ParseContext)#
| Option | Type | Default | Description |
|---|---|---|---|
error |
$ZodErrorMap |
undefined |
Per-call error map overriding schema-level and global locale error messages. |
reportInput |
boolean |
false |
When true, preserves the raw input property on every finalized $ZodIssue (omitted by default to avoid retaining sensitive or large payloads). |
jitless |
boolean |
false |
When true, bypasses eval / new Function JIT fast-path compilation for this parse call. |
import * as z from "zod";
const UserSchema = z.object({
id: z.uuid(),
email: z.email(),
});
// 1. Safe parsing with discriminated result
const res = z.safeParse(UserSchema, rawPayload, { reportInput: true });
if (!res.success) {
console.error(z.prettifyError(res.error));
} else {
console.log(res.data.email);
}
// 2. Boolean type guard via z.validate()
if (z.validate(UserSchema, rawPayload)) {
// rawPayload is narrowed to z.input<typeof UserSchema>
console.log(rawPayload.id);
}
functionz.encode / z.decode / z.safeEncode / z.safeDecode#
While parse always executes in the forward direction (Input -> Output), the codec execution family explicitly pairs forward decode (Input -> Output) with backward encode (Output -> Input).
Codec Execution Signatures#
| Function / Method | Input Parameter Type | Return Type | Direction & Behavior |
|---|---|---|---|
z.decode(schema, value, ctx?) / schema.decode(value, ctx?) |
z.input<T> |
z.output<T> |
Forward (direction: "forward"). Statically requires z.input<T> rather than unknown. |
z.encode(schema, value, ctx?) / schema.encode(value, ctx?) |
z.output<T> |
z.input<T> |
Backward (direction: "backward"). Runs ZodCodec reverse transforms (encode). Throws $ZodEncodeError if the schema graph contains a unidirectional ZodTransform, ZodDefault, or ZodCatch. |
z.safeDecode(schema, value, ctx?) / schema.safeDecode(value, ctx?) |
z.input<T> |
SafeParseResult<z.output<T>> |
Non-throwing forward decode. |
z.safeEncode(schema, value, ctx?) / schema.safeEncode(value, ctx?) |
z.output<T> |
SafeParseResult<z.input<T>> |
Non-throwing backward encode (still throws $ZodEncodeError if an unencodable unidirectional transform is encountered). |
z.decodeAsync / z.encodeAsync / z.safeDecodeAsync / z.safeEncodeAsync |
z.input<T> / z.output<T> |
Promise<...> |
Asynchronous counterparts for codecs with async decode or encode callbacks. |
classZodError & $ZodError#
Validation failures produce an instance of ZodError<T> (in zod, extending native Error) or $ZodError<T> (in zod/v4/core). Note that z.safeParse() uses a lazy getter on { success: false, get error() } so ZodError is only instantiated if .error is actually accessed.
Properties & Methods of ZodError<T>#
| Member | Type | Availability | Description |
|---|---|---|---|
error.issues |
$ZodIssue[] |
zod & zod/v4/core |
Canonical array of finalized validation issues. |
error.message |
string |
zod & zod/v4/core |
Lazy getter returning pretty-printed JSON of error.issues (computed and cached on first read). |
error.name |
"ZodError" | "$ZodError" |
zod & zod/v4/core |
Error class identifier (instanceof Error is true). |
error.flatten(mapper?) |
$ZodFlattenedError<T, U> |
Classic zod (deprecated) |
Prefer standalone z.flattenError(error, mapper). |
error.format(mapper?) |
$ZodFormattedError<T, U> |
Classic zod (deprecated) |
Prefer standalone z.formatError(error, mapper). |
type$ZodIssue & Issue Subtypes#
Zod v4 consolidates issue codes into a clean 11-member discriminated union ($ZodIssue, keyed on issue.code), merging legacy v3 codes (invalid_string, invalid_ReturnValue, invalid_date, invalid_enum_value, invalid_literal) into unified structural types.
Source Code
from drawlib import canvas
from drawlib.diagrams.class_diagram import ClassDiagram, ClassNode
from drawlib.fonts import FontRoboto, FontSourceCode
from drawlib.styles import Styles
canvas.clear()
canvas.setup(width=188, height=104, dpi=150)
cd = ClassDiagram(
node_style=Styles.Neutral.patch(text_font=FontSourceCode.ROBOTO_MONO, text_size=9.5),
header_style=Styles.PrimaryNeutral.patch(text_font=FontRoboto.ROBOTO_BOLD, text_size=10.5),
edge_style=Styles.DarkBold,
edge_text_style=Styles.Dark.patch(text_size=9.5),
title="ZodIssue ($ZodIssueBase) — 11 Discriminated Issue Union Subtypes",
)
# Top Root Interface (ClassNode xy is Center!)
base_issue = cd.add(
ClassNode("$ZodIssueBase", stereotype="interface", width=62, header_style=Styles.SecondaryNeutral.patch(text_font=FontRoboto.ROBOTO_BOLD, text_size=10.5))
.add_attribute("code", "$ZodIssueCode", visibility="+")
.add_attribute("path", "PropertyKey[]", visibility="+")
.add_attribute("message", "string", visibility="+")
.add_attribute("input", "unknown | undefined", visibility="+"),
xy=(94.0, 74.0),
)
# Bottom Row 1: Type, Value & Custom Issues
grp_type = cd.add(
ClassNode("Type, Value & Custom", width=44, header_style=Styles.PrimaryNeutral)
.add_attribute("invalid_type", "{ expected }")
.add_attribute("invalid_value", "{ values: Primitive[] }")
.add_attribute("custom", "{ params?: Record }"),
xy=(23.0, 22.0),
)
# Bottom Row 2: Range, Size & Divisibility Issues
grp_bounds = cd.add(
ClassNode("Range & Divisibility", width=44, header_style=Styles.PrimaryNeutral)
.add_attribute("too_big", "{ origin, maximum }")
.add_attribute("too_small", "{ origin, minimum }")
.add_attribute("not_multiple_of", "{ divisor: number }"),
xy=(70.0, 22.0),
)
# Bottom Row 3: String Format & Object Key Issues
grp_format = cd.add(
ClassNode("Format & Object Keys", width=44, header_style=Styles.PrimaryNeutral)
.add_attribute("invalid_format", "{ format, pattern? }")
.add_attribute("unrecognized_keys", "{ keys: string[] }"),
xy=(117.0, 22.0),
)
# Bottom Row 4: Union & Collection Issues
grp_coll = cd.add(
ClassNode("Union & Collections", width=44, header_style=Styles.PrimaryNeutral)
.add_attribute("invalid_union", "{ errors, discriminator? }")
.add_attribute("invalid_key", "{ origin, issues }")
.add_attribute("invalid_element", "{ origin, key, issues }"),
xy=(164.0, 22.0),
)
cd.connect(grp_type, base_issue, "inheritance", start_side="top", end_side="bottom")
cd.connect(grp_bounds, base_issue, "inheritance", start_side="top", end_side="bottom")
cd.connect(grp_format, base_issue, "inheritance", start_side="top", end_side="bottom")
cd.connect(grp_coll, base_issue, "inheritance", start_side="top", end_side="bottom")
cd.draw(xy=(94.0, 50.0), align="center")
canvas.save()
Complete $ZodIssue Union Reference#
issue.code |
TypeScript Interface | Specific Properties | Emitted By |
|---|---|---|---|
"invalid_type" |
$ZodIssueInvalidType |
expected: $ZodInvalidTypeExpected ("string", "number", "int", "object", class name, etc.) |
All primitive/container type checks, z.instanceof(), z.nonoptional() |
"too_big" |
$ZodIssueTooBig |
origin: "number" | "int" | "bigint" | "date" | "string" | "array" | "set" | "file", maximum: number | bigint, inclusive?: boolean, exact?: boolean |
lt, lte, maxLength, maxSize, length, size |
"too_small" |
$ZodIssueTooSmall |
origin: ..., minimum: number | bigint, inclusive?: boolean, exact?: boolean |
gt, gte, minLength, minSize, length, size |
"invalid_format" |
$ZodIssueInvalidStringFormat |
format: $ZodStringFormats | string, pattern?: string, prefix?: string, suffix?: string, includes?: string, algorithm?: string |
z.email(), z.uuid(), z.iso.*(), regex, startsWith, endsWith, includes, jwt |
"not_multiple_of" |
$ZodIssueNotMultipleOf |
divisor: number |
multipleOf / .step() |
"unrecognized_keys" |
$ZodIssueUnrecognizedKeys |
keys: string[] |
z.strictObject() |
"invalid_union" |
$ZodIssueInvalidUnion |
errors: $ZodIssue[][], discriminator?: string, inclusive?: boolean, matches?: number[] |
z.union(), z.discriminatedUnion(), z.xor() |
"invalid_key" |
$ZodIssueInvalidKey |
origin: "map" | "record", issues: $ZodIssue[] |
z.record(keySchema, ...), z.map(keySchema, ...) |
"invalid_element" |
$ZodIssueInvalidElement |
origin: "map" | "set", key: unknown, issues: $ZodIssue[] |
z.map(..., valSchema), z.set(valSchema) |
"invalid_value" |
$ZodIssueInvalidValue |
values: Primitive[] |
z.literal(), z.enum(), z.nativeEnum(), z.mime() |
"custom" |
$ZodIssueCustom |
params?: Record<string, any> |
.refine(), .superRefine(), z.custom() |
functionz.prettifyError / z.treeifyError / z.flattenError / z.formatError#
Zod v4 provides four tree-shakable top-level error formatting functions that transform a $ZodError (or StandardSchemaV1.FailureResult) into human-readable strings or structured UI error trees.
Error Formatter Comparison#
| Function | Signature | Output Structure | Best Use Case |
|---|---|---|---|
z.prettifyError(error) |
(error: StandardSchemaV1.FailureResult) => string |
Multi-line string with ✖ <message> and → at <dot.path[0]> |
CLI output, server logs, test assertions, LLM prompt feedback |
z.treeifyError(error, mapper?) |
<T, U = string>(error: $ZodError<T>, mapper?: (iss: $ZodIssue) => U) => $ZodErrorTree<T, U> |
Recursive { errors: U[], properties?: { [K]: Tree }, items?: Tree[] } |
Nested forms, complex JSON payloads (replaces legacy formatError) |
z.flattenError(error, mapper?) |
<T, U = string>(error: $ZodError<T>, mapper?: (iss: $ZodIssue) => U) => $ZodFlattenedError<T, U> |
{ formErrors: U[], fieldErrors: { [P in keyof T]?: U[] } } |
Single-level HTML forms and action handlers |
z.formatError(error, mapper?) |
<T, U = string>(error: $ZodError<T>, mapper?: (iss: $ZodIssue) => U) => $ZodFormattedError<T, U> |
Legacy { _errors: U[], [key]: { _errors: U[] } } |
Backward compatibility with Zod v3 .format() consumers |
import * as z from "zod";
const ProfileSchema = z.object({
username: z.string().min(3),
tags: z.array(z.string().min(2)),
});
const result = ProfileSchema.safeParse({ username: "ab", tags: ["ok", "x"] });
if (!result.success) {
// 1. Human-readable CLI string
console.log(z.prettifyError(result.error));
// ✖ Too small: expected string to have >=3 characters
// → at username
// ✖ Too small: expected string to have >=2 characters
// → at tags[1]
// 2. Type-safe nested error tree
const tree = z.treeifyError(result.error);
console.log(tree.properties?.username?.errors); // ["Too small: ..."]
console.log(tree.properties?.tags?.items?.[1]?.errors); // ["Too small: ..."]
}
functionz.config & z.locales#
Global runtime behavior and error message localization are managed through z.config(newConfig?) (backed by globalThis.__zod_globalConfig so CJS and ESM bundles share a single configuration instance) and z.locales.
$ZodConfig Options & Error Precedence#
| Property | Type | Precedence / Effect |
|---|---|---|
customError |
$ZodErrorMap | undefined |
Priority 3 (after schema-level error param [1] and parse-level ctx.error [2]). Global custom error map. |
localeError |
$ZodErrorMap | undefined |
Priority 4 (lowest priority before fallback). Set via z.config(z.locales.ja()), z.locales.en(), etc. |
jitless |
boolean | undefined |
Disables new Function / eval fast-path object & compilation shims globally for strict CSP environments (e.g., Cloudflare Workers / browser extensions). |
memoizer |
$ZodMemoizer | undefined |
Enables cyclic object/array reference tracking during parsing (z.config({ memoizer: z.memoizer() })). Automatically initialized on Classic container schemas. |
import * as z from "zod";
// Switch default error messages to Japanese globally
z.config(z.locales.ja());
// Override specific issue codes globally while delegating others to the locale
z.config({
customError: (issue) => {
if (issue.code === "invalid_type" && issue.input === undefined) {
return "Required field is missing";
}
return undefined; // Fall through to localeError
},
});
class$ZodRegistry & z.globalRegistry#
Zod v4 decouples schema metadata from schema instances using WeakMap-backed $ZodRegistry<Meta, Schema> containers. Because registry entries are held in a WeakMap<Schema, Meta>, ephemeral schemas are garbage-collected normally while registered schemas with an id are also indexed for $defs extraction in z.toJSONSchema().
$ZodRegistry API & Schema Helpers#
| Method / Function | Signature | Description |
|---|---|---|
z.registry<Meta, Schema>() |
registry<T extends object | undefined = object | undefined, S extends $ZodType = $ZodType>(): $ZodRegistry<T, S> |
Creates a new strongly-typed metadata registry constrained to metadata shape T and schema subtype S. |
z.globalRegistry |
$ZodRegistry<GlobalMeta> |
Process-wide singleton registry (globalThis.__zod_globalRegistry) storing GlobalMeta ({ id?, title?, description?, deprecated?, [k: string]: unknown }). |
reg.add(schema, meta) |
add<S extends Schema>(schema: S, meta: $replace<Meta, S>): this |
Associates meta with schema (mutates registry in place; schema.register(reg, meta) is the fluent chainable wrapper). |
reg.get(schema) |
get<S extends Schema>(schema: S): $replace<Meta, S> | undefined |
Retrieves metadata for schema, automatically inheriting non-id metadata from schema._zod.parent clones. |
reg.has(schema) / reg.remove(schema) / reg.clear() |
(schema: Schema) => boolean | this |
Checks existence, removes a single schema, or resets the registry. |
schema.meta(data?) |
meta(): GlobalMeta | undefined / meta(data: GlobalMeta): this |
Reads metadata from z.globalRegistry (0 args) or clones schema and registers data in z.globalRegistry (1 arg). |
schema.describe(description) |
(description: string) => this |
Clones schema and registers { description } in z.globalRegistry. |
[!TIP] Use the phantom symbols
z.$outputandz.$inputinside a custom registry'sMetatype to constrain metadata fields to the registered schema's static output or input type (e.g.,z.registry<{ examples: z.$output[] }>()).
import * as z from "zod";
// Custom registry with type-safe examples tied to each schema's output type
const docRegistry = z.registry<{
id?: string;
title: string;
examples: z.$output[];
}>();
const PortSchema = z.int().min(1).max(65535).register(docRegistry, {
id: "PortNumber",
title: "TCP/UDP Port",
examples: [80, 443, 8080], // Statically checked as number[]!
});
functionz.toJSONSchema & z.fromJSONSchema#
Zod v4 ships native, zero-dependency bidirectional conversion between Zod schemas/registries and JSON Schema (draft-2020-12, draft-07, draft-04, and openapi-3.0).
z.toJSONSchema & z.fromJSONSchema Signatures#
| Function / Method | Signature | Description |
|---|---|---|
z.toJSONSchema(schema, params?) / schema.toJSONSchema(params?) |
(schema: $ZodType, params?: ToJSONSchemaParams) => JSONSchema.BaseSchema |
Converts a single Zod schema into a JSON Schema document. Shared or cyclic subschemas are extracted into $defs (or definitions in Draft-04/07). |
z.toJSONSchema(registry, params?) |
(registry: $ZodRegistry<{ id?: string }>, params?: RegistryToJSONSchemaParams) => { schemas: Record<string, JSONSchema.BaseSchema> } |
Converts all id-tagged schemas in registry into a cross-referenced map of JSON Schemas. |
z.fromJSONSchema(jsonSchema, params?) |
(schema: JSONSchema, params?: { defaultTarget?: JSONSchemaVersion; registry?: $ZodRegistry }) => ZodType |
Parses a JSON Schema object (draft-2020-12, draft-7, draft-4, openapi-3.0) and constructs an equivalent runtime ZodType schema. |
ToJSONSchemaParams Options#
| Option | Type | Default | Description |
|---|---|---|---|
target |
"draft-2020-12" | "draft-07" | "draft-04" | "openapi-3.0" |
"draft-2020-12" |
Target JSON Schema specification version. |
io |
"output" | "input" |
"output" |
Selects whether pipes, codecs, defaults, and coerced schemas emit their "output" or "input" representation. |
metadata |
$ZodRegistry<Record<string, any>> |
z.globalRegistry |
Registry inspected to copy title, description, deprecated, examples, and extract named id definitions. |
unrepresentable |
"throw" | "any" | UnrepresentableHandler |
"throw" |
Behavior when encountering types without a JSON Schema equivalent (z.date(), z.bigint(), z.map(), z.transform()): throw, emit {}, or invoke a custom handler. |
cycles |
"ref" | "throw" |
"ref" |
Emits $ref pointers for recursive schemas ("ref") or throws an error ("throw"). |
reused |
"inline" | "ref" |
"inline" |
Controls whether non-cyclic schemas referenced multiple times are inlined or extracted to $defs. |
override |
(ctx: { zodSchema, jsonSchema, path }) => void |
undefined |
Post-processing hook invoked on each converted node to mutate jsonSchema in place. |
import * as z from "zod";
const UserSchema = z
.object({
id: z.uuid(),
role: z.enum(["admin", "member"]).default("member"),
})
.meta({ id: "User", title: "Platform User" });
// Emit OpenAPI 3.0 input schema
const openApiInput = z.toJSONSchema(UserSchema, {
target: "openapi-3.0",
io: "input",
});
// Reconstruct a runtime Zod schema from a JSON Schema document
const DynamicValidator = z.fromJSONSchema(openApiInput);
typez.infer / z.input / z.output#
In Zod v4, z.input and z.output serve a dual role: they are static TypeScript type helpers (z.input<typeof S>, z.output<typeof S>, z.infer<typeof S>) AND runtime schema projection functions (z.input(schema), z.output(schema)).
Static Type & Runtime Schema Projection Reference#
| Construct | Kind | Signature / Definition | Description |
|---|---|---|---|
z.infer<T> / z.output<T> |
Static Type | T extends { _zod: { output: any } } ? T["_zod"]["output"] : unknown |
Extracts the decoded/parsed output type of schema T. |
z.input<T> |
Static Type | T extends { _zod: { input: any } } ? T["_zod"]["input"] : unknown |
Extracts the raw input type accepted by schema.parse() / z.decode(). |
z.input(schema) |
Runtime Function | <T extends $ZodType>(schema: T) => ZodType<z.input<T>, z.input<T>> |
Traverses schema and replaces every ZodPipe / ZodCodec with its input side (def.in) and every ZodDefault with ZodOptional. |
z.output(schema) |
Runtime Function | <T extends $ZodType>(schema: T) => ZodType<z.output<T>, z.output<T>> |
Traverses schema and replaces every ZodPipe / ZodCodec with its output side (def.out, preserving pipe checks) and unwraps ZodPrefault. |
import * as z from "zod";
const AccountCodec = z.object({
createdAt: z.codec(z.iso.datetime(), z.date(), {
decode: (s) => new Date(s),
encode: (d) => d.toISOString(),
}),
});
// 1. Static Type Extraction
type AccountWire = z.input<typeof AccountCodec>; // { createdAt: string }
type AccountDomain = z.infer<typeof AccountCodec>; // { createdAt: Date }
// 2. Runtime Schema Projection (rewrites pipes/codecs to pure input or output schemas)
const WireOnlySchema = z.input(AccountCodec); // Validates { createdAt: string } -> { createdAt: string }
const DomainOnlySchema = z.output(AccountCodec); // Validates { createdAt: Date } -> { createdAt: Date }