zod

Installation
SKILL.md

Zod

Overview

Zod defines a schema once and gives you both a runtime validator and the TypeScript type (z.infer). The current major version is Zod 4 (zod@4.6.7 checked on 2026-10-12); import { z } from "zod" now resolves to v4. Zod 3 remains importable from "zod/v3", and a tree-shakeable functional variant lives at "zod/mini". Zod 4 deprecates several v3 spellings (listed in Guidelines), which is the main source of outdated code in the wild. Zod also produces JSON Schema with z.toJSONSchema(schema), which is how many LLM tool-calling libraries consume it.

Instructions

  1. Install with npm install zod. Enable "strict": true in tsconfig.
  2. Define schemas with z.object, z.string(), z.number(), z.enum([...]), z.array(), z.record(keySchema, valueSchema) (both arguments are required in v4; the one-argument form is a type error) and infer types with type User = z.infer<typeof User>.
  3. Prefer top-level string formats: z.email(), z.url(), z.uuid(), z.iso.datetime(). The method forms (z.string().email()) still work but are deprecated.
  4. Parse untrusted data with schema.safeParse(data) and branch on result.success; schema.parse throws a ZodError. Use parseAsync / safeParseAsync when a refinement or transform is async.
  5. Format errors with z.flattenError(err) ({ formErrors, fieldErrors }), z.treeifyError(err) or z.prettifyError(err). The err.flatten() and err.format() methods are deprecated. Custom messages: z.string().min(8, "At least 8 characters") or { error: "..." }; .refine(fn, "message") for custom rules.
  6. Coerce strings from query strings and env vars with z.coerce.number(), z.coerce.boolean() (any non-empty string is true, including "false"), z.coerce.date().
  7. Combine schemas with .extend(), .pick(), .omit(), .partial(); use .safeExtend() when the schema carries refinements. .merge() is deprecated; spread A.shape or use .extend(B.shape).
  8. Use z.discriminatedUnion("type", [...]) for tagged unions and z.strictObject / z.looseObject instead of .strict() / .passthrough().
  9. Recursive schemas use getters in v4, no z.lazy or manual type annotation needed.
  10. Transform and chain with .transform() and .pipe(); bidirectional conversions use z.codec(inputSchema, outputSchema, { decode, encode }).
Installs
9
GitHub Stars
197
First Seen
Mar 17, 2026