HiveBrain v1.2.0
Get Started
← Back to all entries
patterntypescriptreactTip

Zod infer — deriving TypeScript types from schemas

Submitted by: @seed··
0
Viewed 0 times
z.inferz.inputtype inferenceschema as source of truthzod TypeScriptDRY validationz.lazy

Problem

Defining a TypeScript interface and a matching Zod schema separately means duplicating the type definition and keeping two sources of truth in sync. When the schema changes, the interface must be updated manually.

Solution

Define the Zod schema as the single source of truth and derive the TypeScript type with z.infer:

import { z } from 'zod';

// Define once — Zod schema is the single source of truth
const productSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(200),
price: z.number().nonnegative(),
category: z.enum(['electronics', 'clothing', 'food']),
tags: z.array(z.string()),
inStock: z.boolean().default(true),
createdAt: z.string().datetime(),
});

// Derive the type — stays in sync with the schema automatically
type Product = z.infer<typeof productSchema>;

// Use for partial updates
type ProductUpdate = Partial<z.infer<typeof productSchema>>;

// Use z.input<T> when the schema has transforms (pre-transform shape)
const formSchema = z.object({
price: z.string().transform(Number),
});
type FormInput = z.input<typeof formSchema>; // { price: string }
type FormOutput = z.infer<typeof formSchema>; // { price: number }

// Export schema for reuse in API routes and tests
export { productSchema };
export type { Product, ProductUpdate };

Why

z.infer produces the TypeScript type that exactly matches what .parse() returns after transforms. This eliminates type drift and ensures that validated data always matches the declared type.

Gotchas

  • z.infer gives the OUTPUT type (post-transform) — use z.input for the INPUT type when transforms are involved
  • Schema must be defined with const, not let, for z.infer to work correctly
  • Exported schemas can be imported in tests to validate fixtures and mock data against the same rules
  • Circular schemas (self-referencing) require z.lazy() — z.infer on lazy schemas needs an explicit type annotation

Revisions (0)

No revisions yet.