1 pontos por GN⁺ 2025-05-20 | 1 comentários | Compartilhar no WhatsApp
  • Lançamento da versão 4 do Zod, uma biblioteca de declaração e validação de esquemas. A versão estável foi lançada com grandes melhorias de desempenho e recursos pedidos há muito tempo
  • Houve grandes melhorias em velocidade e tamanho de bundle, e a nova versão mini (v4-mini) reduz drasticamente o tamanho do bundle
  • Foram adicionados um novo registro de metadados e conversão para JSON Schema, além de inferência de tipos recursivos
  • A experiência do desenvolvedor foi fortalecida com customização de mensagens de erro e um sistema de locale multilíngue
  • A escalabilidade aumentou ainda mais com a introdução de um subpacote core que poderá ser usado na construção de bibliotecas no futuro

Introdução ao Zod 4

Aviso sobre o lançamento principal

  • Após 1 ano de desenvolvimento ativo, o Zod 4 foi lançado como versão estável
  • O desenvolvimento foi realizado com apoio do OSS Fellowship da Clerk
  • Atualmente ele é distribuído em paralelo com o Zod 3, facilitando uma migração gradual para o Zod 4
  • Informações detalhadas sobre algumas mudanças incompatíveis podem ser consultadas no Migration guide

Contexto de crescimento

  • Em comparação com o Zod 3, lançado em 2021, o Zod 4 cresceu exponencialmente em estrelas no GitHub e downloads semanais
  • O Zod 4 é muito mais rápido, mais enxuto e tem melhor eficiência no compilador TypeScript
  • Nove grandes problemas muito pedidos ao longo do tempo foram resolvidos

Benchmarks e desempenho

  • Melhoria de velocidade:
    • Parsing de string: 14,71 vezes mais rápido
    • Parsing de array: 7,43 vezes mais rápido
    • Parsing de objeto (safeParse): 6,5 vezes mais rápido
  • O repositório fornece scripts para executar benchmarks diretamente
  • Graças à estrutura genérica aprimorada, o desempenho de compilação melhorou 10 vezes ao encadear métodos como .extend() e .omit()
  • A velocidade de compilação do TypeScript melhorou significativamente em esquemas e bases de código de grande porte

Tamanho de bundle e Zod Mini

  • O tamanho de bundle padrão foi reduzido em 57%, e a v4 ficou 2,3 vezes menor que a v3
  • zod/v4-mini oferece uma API baseada em funções com tree-shaking, reduzindo o tamanho do bundle em até 85%
  • As diferenças de API entre core e v4-mini estão detalhadas na documentação oficial
  • A estrutura foi projetada para permitir que o bundler remova facilmente métodos não utilizados

Registro de metadados e suporte a JSON Schema

  • É possível registrar e gerenciar typed metadata nos esquemas com tipagem forte
  • O registro global (z.globalRegistry) oferece tratamento de metadados compatíveis com JSON Schema e inclusão automática
  • .meta() e .describe() facilitam a documentação de esquemas
  • Com .toJSONSchema(), é possível converter esquemas para o formato JSON Schema, com metadados refletidos automaticamente

Inferência automática de tipos recursivos

  • Tipos de objetos recursivos e tipos mutuamente recursivos podem ser definidos e inferidos naturalmente sem type casting separado
  • A usabilidade melhorou muito em relação ao padrão do Zod 3
  • Mesmo em tipos recursivos e mutuamente recursivos, todos os métodos de schema continuam disponíveis

Tipo de arquivo e recursos de validação

  • O novo tipo file() permite validar instâncias de File
  • São fornecidas validações para várias restrições de arquivo, como tamanho (min, max) e tipo MIME

Mensagens de erro e sistema de locale

  • A API global de locale (z.locales) permite suporte multilíngue para mensagens de erro
  • A função oficial z.prettifyError oferece formatação de erros mais amigável ao usuário

Funções de formato e template literals

  • Formatos de string existentes (email etc.) foram promovidos para funções de nível superior, melhorando a legibilidade e o tree-shaking
  • São oferecidas várias opções de regex para e-mail, atendendo a diferentes necessidades de validação
  • Suporte a tipos de template literal: facilita a implementação de padrões de string e combinações complexas que podem ser expressos no sistema de tipos

Novos formatos para números e bigint

  • Suporte a inteiros e tipos de ponto flutuante de largura fixa (int32, uint64 etc.)
  • É possível gerar esquemas com restrições mínimas/máximas adicionadas automaticamente dentro de faixas seguras

Introdução ao z.stringbool

  • Permite parsing de booleanos baseados em string (yes, no etc.), incluindo parsing no estilo de variáveis de ambiente
  • Os valores truthy/falsy podem ser customizados

Unificação da API de customização de erros

  • Com o parâmetro unificado error, a estrutura de mensagens de erro e da lógica de tratamento fica mais organizada
  • As várias APIs anteriores relacionadas a erro (message, invalid_type_error, errorMap) foram marcadas como deprecated

Outros aprimoramentos principais

  • Discriminated unions agora oferecem suporte a vários esquemas, aninhamento e combinações
  • .literal() agora permite vários valores ao mesmo tempo
  • Validações customizadas, como .refine(), foram integradas de forma mais intuitiva
  • Com .overwrite() relacionado a transform, é possível fazer pós-processamento sem alterar o tipo transformado

Escalabilidade da biblioteca e novo core

  • Com zod/v4/core, os recursos centrais foram separados em um subpacote próprio, permitindo integração e expansão em várias bibliotecas e plataformas
  • São fornecidos documentos-guia e exemplos de extensão para criadores de bibliotecas

Encerramento

  • O Zod 4 se consolida como uma biblioteca de validação de dados com grandes melhorias em segurança de tipos, desempenho, escalabilidade e experiência do desenvolvedor
  • Novos posts de design e atualizações adicionais já foram anunciados para o futuro
  • Foi preparado um amplo suporte tanto para usuários atuais quanto para criadores de bibliotecas

Desejamos uma ótima experiência de parsing
— Colin McDonnell @colinhacks

1 comentários

 
GN⁺ 2025-05-20
Comentários no Hacker News
  • O próprio autor pede opiniões e fornece uma explicação detalhada sobre a estratégia de versionamento, enfatizando que o npm não é adequado para lidar com uma situação como a do Zod; menciona que inúmeras bibliotecas importam e usam diretamente interfaces/classes do Zod, e que, se o Zod fizer uma mudança grande de versão, todas essas bibliotecas teriam de se adaptar ao mesmo tempo, com risco de explosão de versões; diz que, de forma semelhante ao Go, mudanças incompatíveis podem usar a adição de um novo subcaminho, e que no ambiente TypeScript é possível oferecer suporte simultâneo a "zod/v3" e "zod/v4" com apenas zod@^3.25.0, fornecendo aos usuários finais um caminho de upgrade gradual

    • Agradece pelas contribuições ao Zod e diz estar especialmente animado com as melhorias de desempenho do tsc e com os aprimoramentos em discriminated unions; afirma entender bem a estratégia de versionamento, mas sugere que, para usuários como ele, que não se preocupam com conflitos de dependências transitivas, talvez também fosse bom oferecer uma versão única como pacote 4.0.0; comenta que precisar mudar os imports para "zod/v4" pode gerar ruído no código e trabalho extra, como conflitos com auto import da IDE; ainda assim, considera a atualização muito promissora e agradece

    • Diz que está vendo a notícia pelo celular e pede desculpas caso tenha deixado algo passar; pergunta se o maior incômodo relacionado a .optional() foi incluído entre as 9/10 principais questões resolvidas desta vez; comenta que o Zod é tão bom que continua usando mesmo com incômodos, e agradece pela excelente biblioteca

    • Agradece por poder remover muito código hacky manual na nova versão do Zod; diz que usa zod-key-parser para reduzir typos e pergunta por que esse tipo de recurso não faz parte da biblioteca por padrão, se está fora de escopo ou se ainda não foi implementado; compartilha discussões abertas relacionadas

    • Enfatiza que, muitas vezes, a melhor abordagem é minimizar a dor de curto prazo; menciona como exemplo a enorme confusão da migração do Python 2/3

    • Compartilha que teve bastante dificuldade ao usar ao mesmo tempo tipos recursivos e formas de discriminated union (por exemplo, quando XML fica embutido dentro de JSON), e espera que esta atualização melhore bastante a situação

  • Expressa desconfiança em relação ao import zod/v4-mini, supondo que isso possa até aumentar o tamanho do bundle; diz que, como a documentação oficial recomenda "zod/v4" na maioria dos casos, desenvolvedores de apps usariam zod/v4, mas se autores de bibliotecas também adicionarem zod/v4-mini para reduzir bundle size, ambos poderiam acabar incluídos no bundle, causando duplicação; pergunta se esse problema seria reduzido caso zod/v4 fosse um wrapper de zod/v4-mini

  • Comenta que, para facilitar a migração para o Zod 4, foi adotada uma forma de disponibilizar v3 e v4 ao mesmo tempo em zod@3.25, e critica que essa estrutura, combinada com os limites do gerenciamento de dependências do npm, fez com que o v4 precisasse parecer um v3; aponta ineficiências no sistema de peer dependencies do npm

    • O próprio autor reapresenta a estratégia de versionamento por subcaminhos ao estilo Golang, destacando que, embora seja difícil introduzi-la no ecossistema do Zod por causa das características do npm, ela tem a vantagem de suportar v3 e v4 simultaneamente e permitir uma migração gradual

    • Diz que não concorda necessariamente com a opinião anterior de que o v4 se disfarçou de v3 porque peer dependencies estão quebradas; enfatiza que isso é uma medida para permitir migração gradual, substituindo aos poucos por "zod/v4" e depois concluindo o upgrade completo para v4

    • Ressalta que muita gente está criticando, mas que, na prática, isso é menos uma limitação essencial do npm e mais uma decisão pragmática para permitir uma transição gradual de uma biblioteca com mudanças grandes

    • Comenta que talvez tenha viés por ter usado só npm por muito tempo, mas pergunta qual seria uma forma melhor de dar suporte gradual, em vez de fazer uma migração grande e de uma vez do v3 para o v4

    • Diz que já teve grandes melhorias com o beta do Zod 4, mas que ainda não conseguiu fazer o upgrade direito em um codebase grande por causa da dificuldade com configurações de resolução de módulos; gostaria que também tivesse sido lançado apenas como uma nova versão major, sem camada legada; compartilha a explicação do autor sobre evitar uma “explosão de versões”, mas acrescenta que, na sua opinião, manter suporte ao v3 em paralelo já poderia amortecer o impacto

  • Pergunta como modelar os tipos das respostas do servidor em casos complexos, como quando o tipo retornado muda por endpoint ou quando alguns campos podem vir como null, como no caso de usuários anônimos; comenta que, ao criar várias funções como normalizeUser/normalizePost, a manutenção vai ficando cada vez mais complicada, e pede relatos de como isso é resolvido na prática

    • Oferece uma solução com exemplo de discriminated union, explicando uma abordagem em que a parte comum do schema é definida como objeto e depois expandida conforme cada situação; aconselha que, em casos muito variados, a complexidade pode ser inevitável, mas ao menos um validador de schema ajuda a manter isso de forma organizada

    • Diz que, idealmente, o melhor é definir a estrutura do tipo User em uma única fonte de verdade, por exemplo em forma de discriminated union; assumindo um backend em Python, sugere uma estrutura com vários modelos Pydantic + união e geração de tipos para o cliente TypeScript via OpenAPI/GraphQL code generation

    • Diz que poderia responder melhor com um exemplo real de uso, mas explica que, se o tipo union tiver uma propriedade discriminadora (por exemplo, "user_type"), fica mais fácil acessar os campos individuais, porque o sistema de tipos consegue reconhecer os atributos adequados em cada situação

    • Afirma que o servidor deveria exportar diretamente os tipos; reescrever separadamente todos os tipos no cliente é ineficiente; explica que, em um backend Python, é possível usar Pydantic para gerar automaticamente uma especificação OpenAPI e então gerar os tipos para o cliente TypeScript

    • Menciona que GraphQL foi projetado justamente para casos desse tipo, e que bibliotecas GraphQL em TypeScript conseguem inferir automaticamente a forma do resultado da query, gerando tipos de resposta dinamicamente conforme os campos selecionados

  • Comenta que o Zod 4, apesar das melhorias, ainda é muito mais lento que o ArkType; diz que bibliotecas existentes têm limitações de desempenho por precisarem manter compatibilidade retroativa e a sintaxe; afirma que, ao analisar seu próprio projeto, acabou escolhendo ArkType por desempenho e usabilidade com TypeScript

    • Diz que viu as métricas de velocidade do ArkType e pergunta que impacto prático essa velocidade realmente tem; comenta que, em situações comuns como validação de formulário, isso parece ter pouca influência, então fica na dúvida se ele é usado em cenários sensíveis a desempenho, como validação de entrada em APIs de altíssima velocidade

    • Diz que o ArkType não estava incluído na pesquisa, mas que vinha procurando algo considerando a usabilidade com TypeScript; mesmo assim, não pretende migrar do Zod

    • Diz que teve uma experiência muito difícil ao usar ArkType e que prefere o Zod por ser melhor de usar

    • Pergunta se houve algum motivo especial para escolher ArkType em vez de TypeBox

  • Parabeniza a equipe do Zod pelo novo lançamento; olhando a quantidade de mudanças incompatíveis no guia de migração, manifesta preocupação de que projetos grandes fortemente dependentes de Zod sofram bastante e sejam difíceis de manter; com base na experiência de manter projetos frontend antigos, lamenta a direção atual da evolução do JS, com grandes mudanças em cada biblioteca e documentação insuficiente

    • Diz que mantém vários apps grandes em Next.js e que, no último ano, passou por mudanças grandes e difíceis como Next.js 14→15, Next.js pages→app router, React 18→19, Eslint 8→9 e Tailwind 3→4, e que isso foi realmente pesado; comenta até que chegou a pensar que teria sido melhor usar Django; lembra especialmente que a migração do Tailwind 3→4 foi, surpreendentemente, a mais dolorosa

    • Explica que, para aliviar esse problema, foi adotada a estratégia de oferecer simultaneamente a edição mini; isso facilitaria a transição gradual e, do ponto de vista de otimização de tree-shaking, a introdução do mini teria sido inevitável para competir com alternativas

    • Sugere que migrações desse tipo podem ser feitas sem grande dificuldade com a ajuda de ferramentas como LLMs

  • Diz que o Zod é muito superior às alternativas anteriores, mas que, no desenvolvimento web, a realidade é precisar descrever a mesma estrutura de dados de várias formas: validação de entrada em JS, especificação de API via Swagger, definições separadas no servidor e no cliente etc.; lamenta o quanto isso é repetitivo e trabalhoso

    • Diz lamentar que o TypeScript insista em ser apenas uma ferramenta de checagem estática; não afirma querer verificação em runtime, mas gostaria que os dados de tipo de classes/funções/objetos pudessem ser usados externamente com mais facilidade; hoje, como cada ferramenta precisa definir seus próprios modelos e builders, a duplicação acaba sendo inevitável; compartilha que o projeto de padronização Standard Schema dá sinais de integração com as principais bibliotecas de validação, mas a expansão para especificações de API e ORMs ainda está em estágio inicial

    • Ressalta que o ponto central dessas ferramentas é definir uma vez e propagar type safety para o aplicativo inteiro, enfatizando que o schema do Zod pode servir como uma espécie de fonte única da verdade

    • Acrescenta que muitas pessoas que se incomodam com essa estrutura complicada também demonstram resistência quando alguém propõe unificar tudo com TypeScript (incluindo Zod)

    • Diz que todas as APIs e sistemas estão sempre mudando e em experimentação, e que, embora a realidade com muitas camadas complexas tenha desvantagens, em situações em que “o importante é que o projeto funcione”, isso no fim acaba criando ainda mais trabalho

    • Observa que, no geral, dá para usar type safety ponta a ponta com algo como trpc, mas que isso exige padronizar frontend e backend em TypeScript e dificulta o uso em plataformas fora da web, como mobile, o que é uma limitação prática no trabalho real

  • Diz que não é especialista, mas acha que, por ser baseado em schema, o JSON-Schema pode ser uma boa escolha porque validadores podem ser implementados também em outras linguagens além de TypeScript; pergunta como ele se compara ao Zod com base em exemplos como ajv.js.org

    • Explica que o Zod pode validar não apenas formas JSON, mas objetos JS inteiros, incluindo dados que não podem ser representados em JSON, como datas e instâncias de classes; acrescenta que ele também pode ser usado no processo de conversão para JSON, permitindo escrever schemas baseados em string e, por exemplo, validar e converter uma ISO date string em um objeto Date

    • Diz que o Zod 4 passou a oferecer suporte para converter schemas do Zod em JSON-Schema (antes era preciso uma biblioteca externa), e destaca que um grande diferencial do Zod são os recursos de preprocess/refine, que permitem adicionar callbacks antes da validação, viabilizando transformações flexíveis, como trocar MM/DD/YYYY por DD/MM/YYYY antes de validar — algo que não seria possível em JSON-Schema

    • Diz que JSON-Schema também é uma boa escolha e que, nesse caso, o TypeBox é adequado para geração; comenta que se pode usar avj ou um sistema próprio de validação; validação própria é mais rápida, mas só síncrona, enquanto avj também permite validação assíncrona, o que pode ser vantajoso quando é preciso validação profunda

    • Afirma que, para uso em várias linguagens, JSON-Schema é a opção mais universal, e que, se for encapsulado em OpenAPI, ainda traz a vantagem de gerar documentação de API automaticamente

  • Diz que acabou de começar a adotar o Zod em um projeto novo e que o timing deste lançamento foi perfeito; comenta que, se o cronograma tivesse seguido o esperado, teria precisado de muitas mudanças para migrar ao v4, então o momento foi ideal

  • Diz que se surpreendeu com a quantidade de opiniões negativas; conta que, quando testou as primeiras versões do v4, gostou da nova API, mas estava preocupado com o caminho de migração e até pensou em sugerir o lançamento com um nome de pacote separado; no entanto, avalia que a estratégia adotada pelo autor resolveu o problema de forma excelente, permitindo adotar o v4 imediatamente sem precisar esperar atualizações nas dependências

    • Concorda que, em áreas como validação, não há fôlego para migrar tudo de uma vez, e considera o formato atual a melhor solução prática