zod

TypeScript-first schema validation with Zod v4. Use for schemas, type inference, validation, transformations, and JSON Schema generation.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "zod" with this command: npx skills add thegreataxios/agent-skills/thegreataxios-agent-skills-zod

Zod Development

Zod is a TypeScript-first schema declaration and validation library. Use this skill when defining schemas, validating data, transforming inputs, or working with type-safe APIs.

When to Apply

Reference this skill when:

  • Defining schemas for runtime validation
  • Creating type-safe API boundaries
  • Transforming and coercing data
  • Generating JSON Schema from TypeScript types
  • Validating form inputs, environment variables, or API responses
  • Working with Zod v4's new features (Mini, Core, Codecs)

Quick Reference

Primitive Types

TypeDescriptionExample
z.string()String validationz.string().min(1).max(100)
z.number()Number validationz.number().int().positive()
z.bigint()BigInt validationz.bigint().min(0n)
z.boolean()Boolean valuesz.boolean()
z.date()Date objectsz.date().min(new Date())
z.symbol()Symbol valuesz.symbol()
z.undefined()Undefined onlyz.undefined()
z.null()Null onlyz.null()
z.void()Void typez.void()
z.any()Any type (escape hatch)z.any()
z.unknown()Unknown type (safer)z.unknown()
z.never()Never typez.never()
z.nan()NaN valuez.nan()

String Formats

MethodValidatesExample
.email()Email formatz.string().email()
.url()URL formatz.string().url()
.uuid()UUID formatz.string().uuid()
.ip()IP addressz.string().ip({ version: "v4" })
.cidr()CIDR notationz.string().cidr()
.mac()MAC addressz.string().mac()
.jwt()JWT formatz.string().jwt()
.hash()Hash stringz.string().hash("sha256")
.regex()Custom patternz.string().regex(/^[a-z]+$/)
.emoji()Emoji onlyz.string().emoji()
.cuid() / .cuid2()CUID identifiersz.string().cuid2()
.ulid()ULID identifiersz.string().ulid()
.datetime()ISO datetimez.string().datetime()
.date()ISO datez.string().date()
.time()ISO timez.string().time()
.duration()ISO durationz.string().duration()

String Methods

MethodPurposeExample
.min(n)Minimum length.min(1)
.max(n)Maximum length.max(100)
.length(n)Exact length.length(10)
.startsWith(s)Prefix check.startsWith("https://")
.endsWith(s)Suffix check.endsWith(".com")
.includes(s)Contains substring.includes("@")
.trim()Trim whitespace.trim()
.toLowerCase()Lowercase transform.toLowerCase()
.toUpperCase()Uppercase transform.toUpperCase()
.normalize()Unicode normalize.normalize("NFC")
.nonempty()Min length 1.nonempty()

Number Methods

MethodPurposeExample
.min(n)Minimum value.min(0)
.max(n)Maximum value.max(100)
.int()Integer only.int()
.positive()> 0.positive()
.negative()< 0.negative()
.nonnegative()>= 0.nonnegative()
.nonpositive()<= 0.nonpositive()
.multipleOf(n)Divisible by n.multipleOf(5)
.finite()Not Infinity.finite()
.safe()Safe integer.safe()
.step(n)Stepped values.step(0.01)

Coercion

MethodCoerces FromExample
z.coerce.string()Any to stringz.coerce.string()
z.coerce.number()String/Boolean to numberz.coerce.number()
z.coerce.boolean()String/Number to booleanz.coerce.boolean()
z.coerce.bigint()To BigIntz.coerce.bigint()
z.coerce.date()String/Number to Datez.coerce.date()

Object Methods

MethodPurposeExample
.pick(keys)Select keys.pick({ name: true })
.omit(keys)Remove keys.omit({ password: true })
.partial()All optional.partial()
.required()All required.required()
.extend(obj)Add keys.extend({ age: z.number() })
.merge(schema)Merge schemas.merge(OtherSchema)
.keyof()Keys schema.keyof()
.strict()No extra keys.strict()
.passthrough()Allow extra.passthrough()
.strip()Remove extra.strip()
.catchall(schema)Validate extra.catchall(z.string())

Array Methods

MethodPurposeExample
.min(n)Min items.min(1)
.max(n)Max items.max(10)
.length(n)Exact length.length(5)
.nonempty()Min 1 item.nonempty()

Set Methods

MethodPurposeExample
.min(n)Min size.min(1)
.max(n)Max size.max(10)
.size(n)Exact size.size(5)
.nonempty()Min 1 item.nonempty()

Union Types

TypePurposeExample
z.union()Any of typesz.union([z.string(), z.number()])
z.discriminatedUnion()Tagged unionz.discriminatedUnion("type", [...])
z.xor()Exclusive orz.xor(SchemaA, SchemaB)
z.intersection()All of typesz.intersection(A, B)

Optionality

MethodEffectExample
.optional()T | undefinedz.string().optional()
.nullable()T | nullz.string().nullable()
.nullish()T | null | undefinedz.string().nullish()
.unwrap()Remove wrapperschema.unwrap()

Validation & Transforms

MethodPurposeExample
.refine(fn)Custom validation.refine(v => v > 0)
.superRefine(fn)Multiple issues.superRefine(addIssue)
.check()New v4 validation.check(ctx => ...)
.transform(fn)Transform value.transform(v => v.trim())
.pipe(schema)Chain schemas.pipe(z.string().uuid())
.default(val)Default value.default("unknown")
.prefault(fn)Lazy default.prefault(() => Date.now())
.catch(val)Fallback on error.catch("fallback")

Parsing Methods

MethodReturnsThrows?
.parse(data)TYes
.parseAsync(data)Promise<T>Yes
.safeParse(data)SafeReturnType<T>No
.safeParseAsync(data)Promise<SafeReturnType<T>>No
.spaAlias for safeParseAsyncNo

Error Handling

FunctionPurpose
z.prettifyError(error)Human-readable error
z.treeifyError(error)Tree structure
z.formatError(error)Formatted object
z.flattenError(error)Flattened errors

Metadata

MethodPurposeExample
.describe(text)Add description.describe("User name")
.meta(obj)Custom metadata.meta({ id: "User" })
.register(registry)Register schema.register(registry)

JSON Schema

MethodPurpose
z.toJSONSchema(schema)Convert to JSON Schema
z.toJSONSchema(schema, config)With configuration

Codecs (v4)

Codecs are bi-directional transformations. You define them using z.codec(inputSchema, outputSchema, { decode, encode }):

const stringToDate = z.codec(
  z.iso.datetime(),  // input: ISO date string
  z.date(),          // output: Date object
  {
    decode: (isoString) => new Date(isoString),
    encode: (date) => date.toISOString()
  }
)

// Forward: string → Date
stringToDate.decode("2024-01-15T10:30:00.000Z") // => Date

// Backward: Date → string  
stringToDate.encode(new Date()) // => "2024-01-15T10:30:00.000Z"

Use .decode() for forward processing and .encode() for backward processing.

v4 Features

FeatureDescription
Performance3-10x faster than v3
Bundle SizeUp to 70% smaller
zod/miniFunctional API, tree-shakeable
zod/v4/coreCore utilities package
CodecsBuilt-in encode/decode
JSON SchemaImproved generation

Core Concepts

1. Schema Definition

import { z } from "zod"

const User = z.object({
  id: z.string().uuid(),
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().nonnegative().optional(),
  role: z.enum(["admin", "user", "guest"]).default("user"),
  createdAt: z.coerce.date()
})

type User = z.infer<typeof User>

2. Parsing & Validation

// Parse (throws on error)
const user = User.parse(data)

// Safe parse (returns result)
const result = User.safeParse(data)
if (result.success) {
  console.log(result.data)
} else {
  console.log(result.error)
}

// Async parsing
const asyncUser = await User.parseAsync(data)

3. Transformations

const TrimmedString = z.string().trim().toLowerCase()

const DateFromString = z.string().datetime().transform(val => new Date(val))

const FormattedUser = User.transform(user => ({
  ...user,
  displayName: `${user.name} <${user.email}>`
}))

4. Composition

// Union
const StringOrNumber = z.union([z.string(), z.number()])

// Discriminated Union
const Event = z.discriminatedUnion("type", [
  z.object({ type: z.literal("click"), x: z.number(), y: z.number() }),
  z.object({ type: z.literal("keypress"), key: z.string() })
])

// Intersection
const Combined = z.intersection(BaseSchema, ExtraSchema)

5. Error Customization

const Password = z.string()
  .min(8, "Password must be at least 8 characters")
  .max(100, "Password is too long")
  .regex(/[A-Z]/, "Must contain uppercase letter")

// Per-parse error handling
const result = schema.safeParse(data, {
  error: (issue) => `Custom: ${issue.message}`
})

Common Patterns

API Response Schema

const ApiResponse = <T extends z.ZodTypeAny>(data: T) =>
  z.object({
    success: z.boolean(),
    data: data.optional(),
    error: z.string().optional()
  })

Environment Variables

const Env = z.object({
  NODE_ENV: z.enum(["development", "production", "test"]),
  DATABASE_URL: z.string().url(),
  PORT: z.coerce.number().int().min(1).max(65535).default(3000)
})

const env = Env.parse(process.env)

Recursive Schema

const Node: z.ZodType<TreeNode> = z.lazy(() =>
  z.object({
    value: z.string(),
    children: z.array(Node).optional()
  })
)

Form Validation

const LoginForm = z.object({
  email: z.string().email("Invalid email"),
  password: z.string().min(8, "Password too short"),
  rememberMe: z.boolean().default(false)
})

type LoginInput = z.infer<typeof LoginForm>

How to Work

  1. Import Zod: import { z } from "zod"
  2. Define schema: Use primitives, objects, and composition
  3. Add constraints: Chain methods like .min(), .max(), .email()
  4. Parse data: Use .parse() or .safeParse()
  5. Handle errors: Check .success or use error formatting
  6. Transform if needed: Use .transform() for data transformation

v4 Migration Notes

  • z.custom() now uses z.custom<T>(fn) syntax
  • .refine() returns schema directly (no wrapping)
  • Error messages use new formatting system
  • Use zod/mini for optimal tree-shaking

Related Resources

Related Skills

  • typescript - TypeScript best practices
  • arktype - Alternative validation library

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

Planning with files

Implements Manus-style file-based planning to organize and track progress on complex tasks. Creates task_plan.md, findings.md, and progress.md. Use when aske...

Registry SourceRecently Updated
8.4K22Profile unavailable
Coding

skale-dev

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

bite-dev

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

arktype

No summary provided by upstream source.

Repository SourceNeeds Review