SpikeMe
← Comparativos
Validação de dados

Zod vs Yup

atualizado em 13 de julho de 2026

Zod vs Yup

Zod e Yup comparados por inferência de tipos, obrigatoriedade de campos por padrão e integração com formulários, com dados reais do npm e veredito por contexto.

FatoZodYup
Versão atual4.4.31.7.1
Downloads/semana (npm)224.111.97810.111.879
LicençaMITMIT
Bundle (gzip)60.3 kB13.1 kB
CritérioZodYup
Campos obrigatóriosobrigatórios por padrão, .optional() para liberaropcionais por padrão, .required() para exigir
Fonte do tipo TypeScriptz.infer<typeof schema>yup.InferType<typeof schema>
Validações de formato de stringfunções top-level (z.email(), z.url())métodos encadeados (string().email(), string().url())
Integração histórica com formsadotado por bibliotecas mais recentes (resolvers de react-hook-form, tRPC)historicamente acoplado ao ecossistema Formik
Composição de schemasz.object({...}).extend / z.unionobject({...}).shape / mixed().oneOf
Bundle mínimomaior, biblioteca única com tudo incluídomenor, funções mais isoladas por tipo

Contexto

Um campo que não recebe nenhuma regra explícita de obrigatoriedade se comporta de dois jeitos opostos dependendo da biblioteca de validação escolhida. E essa única decisão de design é a raiz de praticamente toda diferença prática entre Zod e Yup. Em Zod, todo campo de um z.object({...}) é obrigatório por padrão, e fica opcional só quando marcado explicitamente com .optional(). Em Yup, é o oposto: todo campo de um object({...}) é opcional por padrão, e só se torna obrigatório com .required(). Essa inversão se propaga direto para o tipo TypeScript inferido em cada schema, e é a fonte mais comum de superfície de bugs quando alguém troca de uma biblioteca para outra sem revisar os campos um a um.

Yup também é mais antigo no ecossistema JavaScript e nasceu antes da adoção em massa de TypeScript, o que se reflete em como o suporte a inferência de tipos foi incorporado — como uma camada sobre uma API já existente, em vez de ser o ponto de partida do design, como em Zod.

Quando escolher Zod

Zod encaixa quando o time quer que o schema seja a única fonte de verdade e o tipo TypeScript derive dele sem margem para divergência silenciosa, todo campo declarado é obrigatório, a menos que o contrário seja dito explicitamente:

import { z } from "zod";

const User = z.object({
  email: z.email(),
  name: z.string(),
});

type User = z.infer<typeof User>; // { email: string; name: string } — ambos obrigatórios

Nenhum campo do tipo User acima é opcional, porque nenhum foi marcado com .optional(): o comportamento padrão é o mais estrito. Esse ponto de partida reduz o risco de um campo se tornar acidentalmente opcional por esquecimento, o que é especialmente relevante em validação de payloads de API, onde um campo "esquecido como opcional" pode passar dados incompletos adiante sem erro. Zod também vem sendo o padrão adotado por bibliotecas mais recentes do ecossistema TypeScript — resolvers de formulário, geração de schema para tRPC e ferramentas de IA que precisam de schemas estruturados — o que amplia sua superfície de integração além de formulários tradicionais.

Quando escolher Yup

Yup continua sendo uma escolha sólida em projetos que já têm uma base de schemas Yup madura, ou que usam Formik — a combinação Formik + Yup é uma das mais antigas e documentadas do ecossistema React para validação de formulários:

import { object, string, InferType } from "yup";

const userSchema = object({
  email: string().email(),
  name: string().required(),
});

type User = InferType<typeof userSchema>;
// { email?: string | undefined; name: string } — email é opcional por padrão

Note que, no exemplo acima, email não tem .required() e por isso o tipo inferido o marca como opcional — mesmo estando presente no schema. Esse comportamento pode ser exatamente o que um formulário quer (campos que só se tornam obrigatórios sob certas condições, algo que Yup expressa bem com .when()), mas exige atenção redobrada de quem espera o comportamento "obrigatório por padrão" ao qual Zod acostumou parte do ecossistema. Yup também tem suporte maduro e antigo a validação condicional entre campos e a testes assíncronos, um caso de uso presente desde as primeiras versões da biblioteca.

Veredito

Times que já apostaram em Formik leem essa comparação de um jeito; times greenfield, de outro. A resposta muda conforme o ponto de partida, não conforme qual biblioteca é "melhor". Se o time quer que TypeScript seja tratado como fonte de verdade, com campos obrigatórios por padrão e menor risco de divergência silenciosa entre schema e tipo, Zod tende a ser a escolha mais segura para projetos novos. Se o projeto já roda sobre Formik ou tem uma base de schemas Yup estabelecida, ou se a semântica de "opcional por padrão, obrigatório quando necessário" encaixa melhor no domínio (formulários com campos condicionais), Yup continua sendo uma opção madura e bem documentada.

Essa inversão de padrão é também o erro mais comum em migrações mal revisadas entre as duas: um .required() esquecido, ou um .optional() que devia estar lá, passa despercebido até um payload incompleto chegar em produção. Revisar campo a campo continua sendo o único jeito seguro de trocar uma pela outra. Nenhum script automatizado substitui esse trabalho manual.

Zod

Escolha Zod se…

Escolha Zod se o time quer que TypeScript seja a fonte de verdade — schema e tipo derivado sempre em sincronia, com campos obrigatórios por padrão.

Yup

Escolha Yup se…

Escolha Yup se o projeto já usa Formik ou uma base de código legada construída em torno de yup, ou se prefere campos opcionais por padrão com obrigatoriedade explícita.

Este comparativo é genérico: a resposta certa depende das versões, do time e do que já existe no seu projeto.

Gere o spike para a SUA stack

Compartilhar

XLinkedIn