πŸ“š Learning Hub
Β· 5 min read
Last updated on

Zod vs Yup β€” Which Validation Library in 2026?


Zod Won the TypeScript Validation War

It’s 2026 and the debate is effectively over. Zod has become the default schema validation library for TypeScript projects. From tRPC to Next.js server actions to Astro content collections, Zod is baked into the tools developers reach for every day. Yup still works β€” and still has valid use cases β€” but the momentum is undeniable.

This post breaks down exactly where each library stands, with code examples, performance notes, and guidance on when each one still makes sense.

Feature Comparison

FeatureZodYup
Language focusTypeScript-firstJavaScript-first
Type inferencez.infer<typeof schema>Manual type definitions
Bundle size (min+gzip)~13KB~15KB
API styleStrict, chainableFlexible, chainable
Default behaviorStrict (no unknown keys)Permissive (strips unknown)
Async validationSupportedSupported
Custom error messagesPer-field, per-rulePer-field, per-rule
TransformsBuilt-in .transform()Built-in .transform()
Discriminated unionsNative z.discriminatedUnion()Manual workarounds
Recursive schemasz.lazy()yup.lazy()
Ecosystem adoptiontRPC, Next.js, Astro, React Hook FormFormik, older React projects
First release20202014

TypeScript Integration

This is where Zod pulls ahead decisively. Zod was designed so that your schema is your type. You define validation once and infer the TypeScript type directly from it:

import { z } from "zod";

const UserSchema = z.object({
  name: z.string().min(1),
  email: z.string().email(),
  age: z.number().int().positive(),
});

// Type is inferred automatically β€” no duplication
type User = z.infer<typeof UserSchema>;

With Yup, you typically end up maintaining a separate interface alongside your schema:

import * as yup from "yup";

// You need this separately
interface User {
  name: string;
  email: string;
  age: number;
}

const UserSchema = yup.object({
  name: yup.string().required(),
  email: yup.string().email().required(),
  age: yup.number().positive().integer().required(),
});

The duplication isn’t just annoying β€” it’s a source of bugs. When you change the schema but forget to update the interface, TypeScript won’t catch the mismatch. With Zod, that entire category of bug disappears.

API Design Comparison

Both libraries use chainable APIs, but Zod’s defaults are stricter. Zod treats fields as required by default and rejects unknown keys. Yup treats fields as optional unless you call .required() and silently strips unknown keys.

Zod approach for a REST API request body:

const CreatePostSchema = z.object({
  title: z.string().min(1).max(200),
  body: z.string().min(10),
  published: z.boolean().default(false),
  tags: z.array(z.string()).optional(),
});

// Parsing throws on invalid data
const result = CreatePostSchema.safeParse(requestBody);
if (!result.success) {
  console.error(result.error.flatten());
}

Yup equivalent:

const CreatePostSchema = yup.object({
  title: yup.string().required().min(1).max(200),
  body: yup.string().required().min(10),
  published: yup.boolean().default(false),
  tags: yup.array().of(yup.string()),
});

// Validation throws or returns
try {
  const data = await CreatePostSchema.validate(requestBody);
} catch (err) {
  console.error(err.errors);
}

Zod’s safeParse returns a discriminated union β€” either { success: true, data } or { success: false, error } β€” which is more ergonomic in TypeScript than try/catch patterns.

Performance

Both libraries are fast enough for virtually all real-world use cases. Benchmarks show Zod and Yup performing within the same ballpark for typical object validation. If you’re validating thousands of objects per second in a hot loop, you’d look at something like Typia or compiled validators anyway.

For form validation, API route handlers, and content schemas, neither library will be your bottleneck. Pick based on developer experience, not microseconds.

Ecosystem

This is where Zod’s dominance becomes clear:

  • tRPC β€” Zod is the default input validator. See our tRPC vs GraphQL comparison for context.
  • Next.js Server Actions β€” Zod is the recommended validation layer in the official docs.
  • Astro Content Collections β€” uses Zod schemas to define and validate frontmatter.
  • React Hook Form β€” the @hookform/resolvers package supports both, but Zod examples dominate the docs.
  • Nuxt β€” server routes commonly use Zod via H3 validation.
  • Conform β€” React form library built around Zod schemas.

Yup still has strong integration with Formik, which remains popular in legacy React codebases. If your project already uses Formik + Yup, there’s no urgent reason to migrate.

When to Use Zod

  • New TypeScript projects of any size
  • You want a single source of truth for types and validation
  • You’re using tRPC, Next.js, or Astro
  • You want strict defaults that catch bugs early
  • You need discriminated unions or complex schema composition
  • Check our Zod cheat sheet for a quick reference

When to Use Yup

  • Existing projects with Yup already integrated
  • Formik-based forms where migration cost isn’t justified
  • JavaScript-only projects (no TypeScript)
  • Teams that prefer permissive validation defaults

Verdict

Zod is the clear default for new TypeScript projects in 2026. The type inference via z.infer<> eliminates an entire class of bugs, the ecosystem has standardized around it, and the strict-by-default API catches issues earlier. If you’re starting fresh, use Zod.

Yup remains a solid library with no critical flaws. If it’s already in your codebase and working well, a migration isn’t mandatory. But for greenfield work, Zod is the answer.

FAQ

Is Zod better than Yup?

For TypeScript projects, yes. Zod’s type inference via z.infer<> eliminates the need to maintain separate type definitions, and its strict-by-default API catches more bugs at validation time. Yup is still a solid library but lacks the tight TypeScript integration that modern projects demand.

Can I use Zod without TypeScript?

Yes β€” Zod works in plain JavaScript projects. However, you lose the main advantage (automatic type inference), so the benefit over Yup diminishes significantly in a JavaScript-only codebase.

Is Yup still maintained?

Yes, Yup is still actively maintained and receives updates. It remains a reliable choice for existing projects, especially those using Formik. However, its pace of development and ecosystem adoption has slowed compared to Zod.

Which validation library should I use with React Hook Form?

Both work via @hookform/resolvers, but Zod is the recommended choice. React Hook Form’s documentation and examples predominantly feature Zod, and the type inference means your form types stay in sync with validation rules automatically.

πŸ“˜