Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Technology handbook

Zod validation libraries

Runtime schemas, TypeScript inference, transformations, errors, forms, API boundaries and schema composition.

Topics
32
Sections
4

Zod foundations

Runtime validation vs TypeScript

Validate external values at runtime instead of relying on a type assertion that performs no check.

  • Types are erased at build time and check nothing about a real request body.
  • A cast tells the compiler what to assume; a schema tells the program what arrived.
  • Parse at every boundary: request bodies, query strings, storage reads and third-party responses.

parse and safeParse

Choose exception-based parsing or a discriminated success result according to the surrounding error flow.

  • parse throws on failure, which suits code already wrapped in an error handler.
  • safeParse returns a success flag with either the data or the issues, and never throws.
  • A route that renders field errors wants the result object, not an exception.

parseAsync and safeParseAsync

Await parsing when refinements or transformations perform asynchronous work.

  • Any schema with an async check has to be awaited or it throws at parse time.
  • A uniqueness lookup against the database is the usual reason to go async.
  • Keep async work out of a schema used on the hot path of a render.

z.infer, z.input and z.output

Derive types from a schema and distinguish accepted input from transformed output.

  • One schema is the single definition of both the check and the type.
  • Input and output differ as soon as a transform or a default is involved.
  • Type a function argument from the input and its result from the output.

Strings and formats

Apply length, pattern and supported format constraints according to the actual domain contract.

  • Length and pattern rules belong on the schema, not scattered through handlers.
  • Built-in formats cover email, URL, UUID and datetime without hand-written patterns.
  • Trim before checking length, or a padded value passes a rule it should fail.

Numbers and coercion

Reject invalid numeric values and test how empty strings or booleans behave under conversion.

  • A JSON number arrives typed; a query string or form field never does.
  • Coercion accepts anything convertible, so an empty string can become zero.
  • Bound the value with min, max and integer rules after converting it.

Booleans, literals and enums

Model a finite allowed set rather than accepting arbitrary strings for a controlled field.

  • An enum narrows to exactly the members the code has branches for.
  • A literal pins one value, which is what makes a tagged variant work.
  • A checkbox posts a string, so a boolean field needs an explicit mapping.

Optional, nullable and nullish

Distinguish an absent value from an explicit null and decide which the API permits.

  • Optional allows the key to be absent; nullable allows it to be present and null.
  • A patch endpoint needs that distinction to tell skip from clear.
  • Nullish accepts both and is right only when the two truly mean the same thing.

Schema composition

Object schemas

Validate a structured record and choose how unknown properties should be handled.

  • An object schema validates each known key and reports issues by path.
  • Unknown keys are stripped by default, so parsed output carries no extras.
  • Nest schemas to mirror the shape of the payload rather than flattening it.

Strict and loose objects

Reject or preserve extra keys deliberately at public request boundaries.

  • A strict object rejects unknown keys, which catches a renamed client field early.
  • A passthrough object keeps extras, useful when forwarding a payload untouched.
  • Strict at a public ingress point; permissive when wrapping a partner response.

Arrays and tuples

Distinguish a repeated element type from a fixed positional contract.

  • An array checks every element against one schema and can bound its length.
  • A tuple fixes the length and gives each position its own schema.
  • Validating a large array on every request is a real cost worth measuring.

Records, maps and sets

Model keyed collections and unique collections with validation of their contained values.

  • A record validates keys and values when the key names are not known ahead of time.
  • Map and Set schemas check the collection type itself, not just its contents.
  • A record with an unbounded key space is a place to impose a size limit.

Unions

Accept one of several explicit input shapes and provide meaningful errors for unmatched input.

  • A union tries each member and fails only when none matches.
  • The error lists every branch, which reads poorly for more than a few members.
  • Order matters when members overlap, because the first match wins.

Discriminated unions

Use a literal tag to select a variant and simplify downstream type narrowing.

  • A shared literal key selects one branch instead of trying them all.
  • Errors come from the matched variant, so the message points at the real problem.
  • Parsing stays fast because only one member is ever evaluated.

Intersections

Combine compatible requirements while understanding how the resulting values are merged.

  • An intersection requires a value to satisfy both schemas at once.
  • Conflicting requirements make a schema nothing can satisfy, with no warning.
  • Extending an object is usually clearer than intersecting two of them.

pick, omit and partial

Derive related object contracts without accidentally weakening required production checks.

  • Derive a narrower contract from the canonical schema rather than restating it.
  • A partial schema suits a patch body where every field is genuinely optional.
  • Partial applied to a create schema quietly drops the checks that mattered.

extend and schema reuse

Compose fields from shared contracts and avoid incompatible overrides.

  • Extend adds fields and can also replace one, which silently relaxes it.
  • Keep shared field definitions in one place so a rule changes once.
  • A base schema plus per-endpoint extensions beats one schema with everything optional.

Recursive schemas

Describe nested structures with explicit recursion and realistic size or depth limits.

  • A self-referencing schema needs a lazy wrapper or the definition cannot close.
  • Annotate the type by hand, since inference cannot resolve the cycle alone.
  • Cap the depth, or a deliberately nested payload becomes a denial of service.

Rules & transformations

refine and superRefine

Express domain rules that primitive constraints cannot represent and attach issues to useful paths.

  • refine adds one predicate with one message to an already-parsed value.
  • superRefine can add several issues and attach each to its own path.
  • Refinements run only after the base checks pass, so ordering is predictable.

Cross-field validation

Validate relationships such as matching passwords or a start date preceding an end date.

  • A rule spanning two fields belongs on the object, not on either field.
  • Attach the issue to the field the user must change, not to the object root.
  • Confirm-password and date-range checks are the cases that come up first.

Transforms

Convert accepted values into application-ready output while tracking the changed output type.

  • A transform reshapes the value after validation, so output stops matching input.
  • Normalising a string or splitting a name is a transform, not a check.
  • A transformed schema can no longer be used to validate its own output.

Preprocessing

Normalize raw input before validation only when the normalization is part of the intended contract.

  • Preprocessing runs before validation and can convert a value into a valid one.
  • Use it for genuine normalisation such as trimming, never to paper over bad input.
  • A preprocessor that swallows errors makes failures impossible to diagnose.

Pipelines and codecs

Compose validation and conversion stages, checking support in the installed Zod release.

  • A pipeline feeds one schema output into the next schema input.
  • It keeps a parse step and a domain check separate rather than merged into one refine.
  • Support differs between releases, so confirm what the installed version offers.

Defaults and fallbacks

Distinguish a value supplied for missing input from recovery after invalid input.

  • A default fills in a missing value before validation runs.
  • A fallback replaces the result after validation fails, hiding the failure.
  • A fallback on a security-relevant field turns bad input into a valid request.

Branded and readonly types

Add type-level distinctions while understanding what runtime guarantees are actually enforced.

  • A brand separates a validated identifier from any other string in the type system.
  • The brand exists only at compile time and costs nothing at runtime.
  • Readonly stops accidental mutation in code but does not freeze the object.

Metadata and JSON Schema

Export schema descriptions where supported and inspect how non-JSON transformations are represented.

  • Descriptions carried on a schema can generate documentation from the same source.
  • Export to JSON Schema only covers constructs that format can express.
  • A transform has no JSON Schema equivalent and is dropped from the export.

Validation integration

Error formatting

Turn structured issues into field and form errors without discarding nested paths.

  • Every issue carries a path, so a nested failure can reach the right input.
  • Flatten for a simple form; walk the tree when fields are nested or repeated.
  • Collect all issues rather than showing the user one mistake at a time.

Custom error messages

Give precise corrective feedback while avoiding disclosure of sensitive internal constraints.

  • A message written for the field beats a generic type complaint.
  • Say what is required, not what the internal rule is called.
  • Do not leak limits or internal names that reveal how the backend is built.

FormData validation

Handle strings, repeated fields and files before assuming browser form values match domain types.

  • Every form value arrives as a string, including numbers and checkboxes.
  • A repeated field name yields several entries that must be collected into an array.
  • A file input needs size and type checks before anything touches storage.

API request and response schemas

Validate ingress and assert egress contracts without exposing private database fields.

  • Validate ingress so a handler never works on an unchecked shape.
  • Parse the response too, so an internal field cannot leak into the payload.
  • Sharing the schema with the client keeps both ends on one contract.

Environment validation

Fail early on missing server settings while preventing secrets from entering public client configuration.

  • Check configuration once at startup rather than at first use.
  • A missing setting should stop the process, not surface as a runtime failure later.
  • Keep server settings in a schema the client bundle never imports.

Schema testing and migration

Test valid, invalid and boundary cases before changing a contract used by existing clients.

  • Test the boundaries: empty, maximum length, wrong type and extra keys.
  • Tightening a live schema rejects payloads that used to work, so stage it.
  • Accept both shapes during a migration window, then drop the old one.

Sources

  • Zod validation libraries official documentation

Ask follow-up questions on any topic in your dashboard.

Start learning