1 pontos por GN⁺ 2025-05-20 | 1 comentários | Compartilhar no WhatsApp
  • O Zod 4 foi lançado como versão estável após 1 ano de desenvolvimento, corrigindo limitações de design do Zod 3 e melhorando bastante desempenho, tamanho do bundle e eficiência de compilação do TypeScript
  • O Zod 3, lançado em maio de 2021, cresceu de 2.700 estrelas no GitHub e 600 mil downloads semanais para atuais 37,8 mil estrelas e 31 milhões de downloads semanais; após 24 versões minor, melhorias importantes passaram a exigir mudanças incompatíveis
  • Nos benchmarks, o parsing de strings ficou 14 vezes mais rápido, o de arrays 7 vezes, e o de objetos 6,5 vezes; as instanciações de tipo do tsc em um exemplo simples também caíram de mais de 25.000 para cerca de 175
  • O tamanho do bundle principal, em gzip, caiu de 12.47kb no Zod 3 para 5.36kb na versão normal do Zod 4, e o Zod Mini, com API funcional compatível com tree shaking, reduz isso para 1.88kb
  • Os novos recursos incluem conversão para JSON Schema, registro de metadados, inferência de tipos de objetos recursivos, internacionalização, pretty-printing de erros, tipos template literal, z.stringbool(), parâmetro error unificado e melhorias em z.discriminatedUnion()

Por que o Zod 4 virou uma nova major version

  • O Zod 4 se tornou estável após 1 ano de desenvolvimento ativo, implementando recursos há muito pedidos sobre uma base mais rápida, menor e mais eficiente no tsc
  • O Zod v3.0 foi lançado em maio de 2021 e, na época, tinha 2.700 estrelas no GitHub e 600 mil downloads semanais
  • Hoje, o Zod registra 37,8 mil estrelas no GitHub e 31 milhões de downloads semanais
    • Há 6 semanas, quando a beta saiu, eram 23 milhões de downloads semanais
  • Com 24 versões minor acumuladas, a base de código do Zod 3 chegou ao limite, e os recursos e melhorias mais pedidos exigiam mudanças incompatíveis
  • O Zod 4 fechou 9 dos 10 issues públicos mais votados

Desempenho de parsing e eficiência de compilação do TypeScript

  • O Zod 4 fornece benchmarks que podem ser executados diretamente no repositório
  • Melhorias de desempenho no parsing:
    • Parsing de strings: 14 vezes mais rápido
    • Parsing de arrays: 7 vezes mais rápido
    • Parsing de objetos: 6,5 vezes mais rápido
  • O benchmark de parsing de objetos usa o Moltar validation library benchmark
  • Com base em tsc --extendedDiagnostics, a compilação de um arquivo simples reduziu fortemente as instanciações de tipo
    • Usando "zod/v3": mais de 25.000 vezes
    • Usando "zod/v4": cerca de 175 vezes
  • O Zod 4 redesenhou e simplificou os genéricos de ZodObject e de outras classes de schema para evitar a explosão de instanciações
  • O padrão de encadear repetidamente .extend() e .omit() levava 4000ms para compilar no Zod 3, e chamadas adicionais de .extend() podiam causar o erro "Possibly infinite"
  • O mesmo padrão compila em 400ms no Zod 4, ficando 10 vezes mais rápido
  • No futuro, com o compilador tsgo, o desempenho do editor com Zod 4 pode se estender a schemas e bases de código maiores

Tamanho do bundle e Zod Mini

  • O tamanho do bundle principal foi comparado empacotando um script simples de validação com z.boolean() usando rollup
  • Tamanho do bundle principal em gzip:
    • Zod 3: 12.47kb
    • Zod 4 versão normal: 5.36kb
  • O bundle principal da versão normal do Zod 4 é cerca de 57% menor que o do Zod 3, uma redução de 2,3 vezes
  • A API centrada em métodos do Zod é inerentemente difícil de aplicar tree shaking, e até um script simples com z.boolean() acaba puxando implementações não usadas como .optional() e .array()
  • O Zod Mini oferece uma API funcional com tree shaking e correspondência 1:1 com zod
    • Onde o Zod usa métodos, o Zod Mini normalmente usa funções wrapper
    • Os métodos de parsing são iguais no Zod e no Zod Mini
    • O método genérico .check() adiciona refinamentos
  • O Zod normal continua sendo recomendado para a maioria dos casos de uso, enquanto projetos com restrições anormalmente rígidas de tamanho de bundle podem considerar o Zod Mini
  • Ao usar zod/mini, o tamanho do bundle em gzip fica em 1.88kb
    • Redução de 85% e 6,6 vezes em relação ao Zod 3
    • Tabela comparativa: Zod 3 12.47kb, Zod 4 normal 5.36kb, Zod 4 Mini 1.88kb
  • Mais detalhes podem ser vistos na documentação de zod/mini

Metadados e JSON Schema

  • O Zod 4 introduz um novo sistema para adicionar metadados fortemente tipados aos schemas
  • Os metadados são armazenados não no próprio schema, mas em um schema registry que vincula o schema aos typed metadata
  • É possível criar um registro com z.registry(), e o método .register() do schema também permite um registro conveniente
  • O Zod exporta z.globalRegistry, um registro global que recebe metadados compatíveis com JSON Schema comum
  • O método .meta() adiciona convenientemente o schema ao z.globalRegistry
  • Para compatibilidade com o Zod 3, .describe() continua disponível, mas no Zod 4 o recomendado é .meta()
  • O Zod 4 oferece conversão nativa para JSON Schema por meio de z.toJSONSchema()
  • Os metadados de z.globalRegistry são incluídos automaticamente na saída de JSON Schema
  • Informações de customização do JSON Schema gerado estão na documentação de JSON Schema

Novas representações de schema e recursos de tipos

  • O Zod 4 consegue inferir corretamente tipos de objetos recursivos
    • É possível representar tipos recursivos e tipos mutuamente recursivos
    • Diferentemente do padrão de tipos recursivos do Zod 3, não é necessário type casting
    • O schema resultante é uma instância normal de ZodObject e pode usar todo o conjunto de métodos
  • Foi adicionado um File schema para validar instâncias de File
  • z.templateLiteral() representa os tipos template literal do TypeScript
    • Tipos de schema do Zod que podem ser convertidos em string armazenam regex internos
    • Os alvos incluem strings, formatos de string como z.email(), números, boolean, bigint, enum, literal, undefined/optional, null/nullable e outros template literals
    • O construtor z.templateLiteral concatena tudo isso em uma super-regex
    • Formatos de string como z.email() são corretamente aplicados, mas refinamentos customizados não são aplicados
    • Mais detalhes estão na documentação de template literals
  • Foram adicionados novos formatos numéricos para representar inteiros de largura fixa e tipos de ponto flutuante
    • Eles retornam instâncias de ZodNumber com as restrições adequadas de mínimo/máximo inclusivo já aplicadas
  • Também foram adicionados formatos numéricos bigint que ultrapassam o intervalo que o JavaScript number consegue representar com segurança
    • Eles retornam instâncias de ZodBigInt com as restrições adequadas de mínimo/máximo inclusivo já aplicadas
  • z.literal() agora pode receber opcionalmente vários valores

Erros, internacionalização e formatos de string

  • O Zod 4 introduz uma nova API de locales para traduzir globalmente mensagens de erro para vários idiomas
  • A lista completa de locales suportados está em Customizing errors e será atualizada conforme novos idiomas forem adicionados
  • O Zod implementa a função de topo z.prettifyError, que transforma ZodError em uma string em formato amigável ao usuário
    • O formato atual não pode ser configurado
    • Ele pode mudar no futuro
    • Quem já usa zod-validation-error pode continuar usando
  • Todos os formatos de string, como email, foram promovidos a funções de topo do módulo z
    • Isso é mais conciso e favorece tree shaking
    • A API equivalente baseada em método, como z.string().email(), ainda pode ser usada, mas está deprecated
    • Ela deve ser removida na próxima major version
  • A API z.email() suporta regular expressions customizadas
    • Não existe um único regex canônico para email, e cada aplicação pode optar por critérios mais rígidos ou mais flexíveis
    • O Zod exporta alguns regex comuns por conveniência

Coerção de boolean e simplificação da customização de erros

  • O antigo z.coerce.boolean() é uma API simples que converte valores falsy em false e valores truthy em true
    • false, undefined, null, 0, "", NaN etc. viram false
    • Esse comportamento está alinhado com as outras APIs z.coerce
  • Para uma coerção de boolean mais sofisticada, no estilo de variáveis de ambiente, o Zod 4 introduz z.stringbool()
  • A maior parte das mudanças incompatíveis do Zod 4 está relacionada à API de customização de erros
  • A customização de erros foi unificada em um único parâmetro error
    • message foi substituído por error
    • O parâmetro message continua suportado, mas está deprecated
    • invalid_type_error e required_error foram substituídos por error na sintaxe de função
    • errorMap também foi substituído por error na sintaxe de função

Composabilidade, refinamentos e transformações

  • z.discriminatedUnion() passou a suportar vários tipos de schema que antes não eram aceitos
    • Incluindo union e pipe
    • Agora é possível usar um discriminated union como membro de outro discriminated union, tornando-o componível
  • No Zod 3, os refinamentos eram armazenados na classe ZodEffects, que envolvia o schema original
    • Essa estrutura dificultava combinar .refine() com outros métodos de schema, como .min()
  • No Zod 4, os refinamentos são armazenados dentro do schema, permitindo usar .refine() e outros métodos de forma natural em conjunto
  • O novo método .overwrite() representa transforms que não mudam o tipo inferido
    • .transform() tem tipo de saída que não pode ser inspecionado em runtime, e a função de transformação é uma caixa-preta que pode retornar qualquer coisa
    • Por isso, não há uma forma segura de convertê-lo para JSON Schema
    • .overwrite() retorna uma instância da classe original
    • A função de overwrite é armazenada como refinement e não altera o tipo inferido
  • Os métodos existentes .trim(), .toLowerCase() e .toUpperCase() foram reimplementados usando .overwrite()

Base para autores de bibliotecas

  • Com a adição do Zod Mini, foi criado o subpacote zod/v4/core, que reúne os recursos centrais compartilhados entre Zod e Zod Mini
  • zod/v4/core expande o Zod de uma biblioteca simples para uma base rápida de validação que pode ser embutida em outras bibliotecas
  • Quem estiver criando uma biblioteca de schemas pode se basear nas implementações de Zod e Zod Mini para construir sobre zod/v4/core
  • Para autores de bibliotecas, há o guia For library authors
    • Ele cobre best practices para construir sobre o Zod
    • Responde dúvidas comuns sobre como oferecer suporte simultâneo a Zod 3, Zod 4 e Mini

1 comentários

 
GN⁺ 2025-05-20
Opiniões no Hacker News
  • Sou o autor; perguntem o que quiserem. Sobre a política de versões, deixei a justificativa dessa abordagem descrita com bastante detalhe: https://github.com/colinhacks/zod/issues/4371
    No fim, o npm não foi projetado para lidar bem com a situação em que o Zod se encontra. Dezenas a centenas de bibliotecas importam diretamente interfaces/classes do Zod e as usam em suas APIs públicas, então, toda vez que o Zod sobe uma versão major, essas bibliotecas também precisam lançar uma nova major
    Isoladamente isso é razoável, mas no Zod pode criar uma avalanche de versões dolorosa para todo mundo, e parecia provável que uma parte considerável do ecossistema ficasse presa para sempre na v3
    Por isso, de forma parecida com o Go, optamos por adicionar um novo subcaminho em vez de o pacote lançar uma nova versão com quebra de compatibilidade. No ecossistema TypeScript, uma biblioteca pode ter apenas zod@^3.25.0 como peer dependency e dar suporte às duas versões ao mesmo tempo importando o que precisa de "zod/v3" e "zod/v4"

    • A melhoria de desempenho do tsc em bases de código grandes é especialmente bem-vinda, e as mudanças em uniões discriminadas também parecem que vão ajudar bastante em certos cenários que até agora eram deficientes
      Ainda assim, embora eu entenda o motivo de terem escolhido uma política de versões um tanto estranha por causa de circunstâncias especiais, do ponto de vista de equipes que não precisam se preocupar com conflitos de versões do Zod em dependências transitivas, eu gostaria que também existisse um pacote 4.0.0
      Se entendi corretamente, será preciso trocar os imports para "zod/v4", o que é uma mudança bem barulhenta, e pode ser trabalhoso ter que pegar com regra de lint o problema de a IDE fazer autoimport a partir de 'zod'
    • Essa abordagem é muito razoável. Também significa que atualizações de segurança de versões anteriores podem ser fornecidas dentro do mesmo release da base de código
    • Estou no celular, então não vi se isso já está no texto, mas fico curioso se corrigir o .optional() no TypeScript está entre as 9 ou 10 principais issues resolvidas: https://github.com/colinhacks/zod/issues/635
      Esse foi o maior incômodo para mim no Zod, mas o Zod é tão bom que sigo usando apesar disso
    • Acho que os novos recursos vão permitir remover muitos hacks temporários que eu tinha feito localmente. Para evitar erros de digitação em nomes de formulários, uso uma versão própria de https://github.com/raflymln/zod-key-parser, e me surpreendeu que esse tipo de recurso não tenha entrado diretamente na biblioteca
      Fico curioso se vocês consideram isso fora do escopo do Zod ou se simplesmente ainda não houve tempo para implementar. A discussão relacionada está em https://github.com/colinhacks/zod/discussions/2134
    • Se isso significa que a versão mais antiga do Zod 4 é 3.25.0, então soa meio sem sentido
      Venho usando a versão alfa do Zod há meses e queria simplesmente ajustar o package.json para fazer o upgrade, mas agora parece que vou ter que vasculhar todo o histórico do git
      Sou muito grato pelo projeto, mas, quanto a esse feedback, acho que tornaram isso mais difícil do que precisava ser. Imagino que poderiam ter publicado também uma 4.x junto com a 3.x
  • O trecho dizendo que “para simplificar a migração, o Zod 4 será distribuído junto com o Zod 3 como parte do release zod@3.25, e importado pelo subcaminho "/v4"” parece um sinal de que o gerenciamento de dependências do npm está completamente bagunçado
    As peer dependencies estão tão quebradas que a v4 precisa fingir que é a v3

    • Sou o autor. A justificativa dessa abordagem está descrita com bastante detalhe aqui: https://github.com/colinhacks/zod/issues/4371
      É verdade que o npm não lida bem com a situação em que o Zod se encontra. Dito isso, o Zod tem a restrição de praticamente não receber nenhuma biblioteca. Dezenas a centenas de bibliotecas importam diretamente interfaces/classes de "zod" e as usam em suas APIs públicas
      Essas bibliotecas precisam lançar uma nova major toda vez que o Zod sobe uma versão major, e no Zod isso poderia causar uma avalanche de versões dolorosa para todos. Sinceramente, parecia que uma parte considerável do ecossistema ficaria presa para sempre na v3
      Por isso, de forma semelhante ao Go, em vez de lançar uma nova versão de pacote a cada release com quebra de compatibilidade, optamos por adicionar um novo subcaminho. No ecossistema TypeScript, é possível dar suporte simultâneo a "zod/v3" e "zod/v4" com uma única peer dependency zod@^3.25.0
    • Não acho correta a conclusão de que “as peer dependencies estão quebradas, então a v4 finge ser a v3”. Vejo o fato de o Zod v4 estar incluído dentro da v3 como uma forma de permitir que os usuários migrem gradualmente
      Ou seja, refatorar os pontos de uso um a um para import ... from 'zod/v4' e, quando terminar, subir completamente para a v4
    • Dá a impressão de que qualquer comentário negativo recebe upvotes. Essa decisão parece mais uma forma prática de permitir a migração gradual de bibliotecas com muitas mudanças com quebra de compatibilidade do que uma limitação intrínseca do próprio npm
    • Talvez eu tenha ficado com a visão limitada por usar só npm por anos, mas fico curioso sobre qual seria uma forma melhor de fazer uma migração iterativa da v3 para a v4 sem uma grande mudança de uma vez só
    • Isso não é um problema exclusivo do npm. O problema de uma dependência depender de uma versão antiga por meio de outra dependência transitiva aparece em praticamente todos os ecossistemas
      Pelo contrário, o npm oferece mais rotas de escape, já que permite executar várias versões ao mesmo tempo quando necessário ou sobrescrever seletivamente partes do grafo de dependências transitivas
      Qual sistema de gerenciamento de pacotes resolve esse problema? Mesmo plataformas “estáveis” como Maven lidam com isso versionando em um novo namespace, como quando o Apache Commons passou da v2 para a v3
  • Há uma pergunta que tenho há muito tempo. Ouvi dizer que o Zod poderia se encaixar nisso, mas, mesmo olhando a documentação, não sei muito bem como fazer
    Suponha que uma API de servidor retorne tipos mais refinados do que ela consegue expressar. Por exemplo, api/:postid/author retorna um User, mas ele pode ser um User comum ou um User anônimo, então campos como username e location podem vir como null. Nesse caso, talvez você queira representar o objeto User como uma união discriminada
    Objetos vindos de outros endpoints também podem precisar de conversão de tipo. Às vezes um User inclui Post[], e um Post pode ter propriedades especiais se for uma postagem de moderador
    No passado, escrevi funções como normalizeUser() e normalizePost(), mas isso rapidamente ficou bagunçado. Cada endpoint retornava subconjuntos diferentes do modelo User/Post, então acabei criando umas 5 versões de normalizePost, o que ficou caótico demais. Fico curioso sobre como esse tipo de problema costuma ser resolvido

    • Acho que dá para usar uniões discriminadas
      A ideia é separar objetos success e failed com base em um campo discriminador, como status. Se houver muitas propriedades especiais para moderadores, mas você não quiser listar ou verificar todas, pode definir um comportamento de passagem
      Mesmo que vários métodos tenham esquemas diferentes, se houver uma parte comum, você pode criar um schema de objeto compartilhado e então criar objetos que adicionem campos extras a ele. Se houver muitas possibilidades, ainda vai ficar bagunçado, mas, se a situação já é bagunçada, pelo menos o validador consegue validar essa bagunça
    • Idealmente, deveria haver uma fonte única da verdade para quais formas um User pode assumir. Isso poderia ser uma união discriminada como User e AnonymousUser
      Se não for full-stack TypeScript, por exemplo em um backend Python, você pode definir as várias formas de User como modelos Pydantic e unions, e gerar tipos de cliente TypeScript por meio da geração de schemas OpenAPI/GraphQL e geração de código
    • Seria preciso entender melhor o caso de uso para resolver, mas adicionar uma propriedade discriminadora como "user_type" a todos os tipos dentro da union facilita lidar com os casos comuns e especiais
      Por exemplo, se você verificar user.user_type === 'authenticated', o sistema de tipos passa a saber que, depois disso, você pode usar user.name
    • Não ajuda diretamente neste caso, mas GraphQL foi criado para isso
      Bibliotecas TypeScript para consultas GraphQL conseguem inferir dinamicamente a forma da resposta a partir dos campos selecionados. Se você selecionar { user { username posts { text } } }, o tipo de resposta terá posts; se selecionar apenas { user { username } }, a propriedade posts ficará completamente ausente
    • O servidor precisa exportar os tipos. Não faz sentido escrever os tipos manualmente no cliente
      O servidor sabe quais dados envia, então deveria fornecer essa informação ao cliente como metadados. Na prática, isso pode ser um backend Python usando schemas Pydantic, gerando automaticamente uma especificação OpenAPI com base neles, e então o cliente gerando os tipos
  • O Zod é muito melhor do que as alternativas que vi, mas às vezes o próprio fato de essa validação explícita ser necessária parece uma falha de onde o desenvolvimento web moderno chegou
    No desenvolvimento full-stack, é frustrante demais ter que descrever a mesma forma de várias maneiras. Acabamos precisando de validação de entrada em JS, Swagger para definição de API, validação de entrada no servidor, ORM para conformidade com o schema, além de definições TypeScript separadas no servidor e no cliente, o que é tedioso

    • O fato de o TypeScript insistir em ser um sistema apenas de verificação estática/em tempo de compilação é uma ferida lamentável para todo o ecossistema. Não quero que o TypeScript vire um verificador em runtime, mas gostaria que ele exportasse dados de tipo úteis para classes, funções e objetos
      O TypeScript parece a melhor fonte única da verdade que temos, mas, na prática, as ferramentas que tentam fazer reflexão acabam redefinindo seus próprios modelos e builders. Há pelo menos 5 grandes áreas em que reflexão é central, e cada uma tem várias implementações
      A antiga ferramenta de emissão de tipos do TypeScript, reflect-metadata, fornece algumas informações de tipo em runtime, mas mira especificações muito antigas de decorators e metadados: https://www.npmjs.com/package/reflect-metadata
      Talvez estejamos no começo de uma unificação. O projeto Standard Schema parece ter suporte da maioria das principais bibliotecas de validação. Ainda assim, estender isso para definições de API ou ferramentas de ORM ainda está em estágio bem inicial
      https://github.com/standard-schema/standard-schema?tab=readm...
    • Na verdade, esse é o ponto central desse tipo de ferramenta. Você define uma vez só e gera dinamicamente tudo que vem abaixo
      Se você altera uma vez no schema Zod, isso se propaga por toda a aplicação junto com a checagem de tipos. O schema Zod acaba sendo a fonte única da verdade
    • Normalmente não é preciso redefinir os dados em vários lugares. Há uma quantidade enorme de ferramentas que convertem para Zod ou a partir de Zod
      Se você já tem um schema JSON Schema/Swagger, é só gerar o Zod a partir dele. Se usa um ORM TypeScript, quase certamente existe um gerador de Zod
      Sinceramente, o Zod é tão amplamente usado que, para mim, virou uma definição de schema unificada da qual outras partes da stack podem depender. Como os tipos são definidos diretamente, os desenvolvedores de fato os mantêm atualizados. A documentação Swagger da empresa está sempre atrás das mudanças
    • Todas as APIs são experimentais e estão em constante mudança e evolução, e o mesmo vale para a web
      O status quo só é aceitável quando você lida com clientes e empregadores que querem apenas o resultado e não se importam com o método. Nesse contexto, essas infelizes camadas de complexidade pelo menos aumentam as horas faturáveis
    • Acho que muitas das pessoas que reclamam que o desenvolvimento web moderno é complexo também detestariam a proposta de substituir tudo isso simplesmente por TypeScript e Zod
      Claro, partindo do pressuposto de que Zod seja a biblioteca escolhida por elas para definição de schemas e validação em TypeScript
  • O Zod 4 parece bom, mas, mesmo incluindo as melhorias mais recentes, o ArkType ainda é várias vezes mais rápido, na casa de um dígito
    Às vezes, por compatibilidade retroativa e compatibilidade de sintaxe, é difícil deixar algo tão mais rápido quanto uma biblioteca totalmente recomeçada do zero. Analisei todas essas ferramentas em um projeto recente e escolhi o ArkType em parte por esse motivo. Também achei a experiência com TypeScript melhor

    • Vi os indicadores de velocidade e fiquei curioso se você consegue explicar onde essa velocidade faz diferença
      Usamos Zod só para validação de formulários, então fico pensando: “por que isso importa?”. Imagino se há casos em que as pessoas validam coisas como mensagens de entrada de APIs de alta vazão, em que desempenho passa a ser mais importante
    • Fiquei curioso sobre por que você escolheu ArkType em vez de TypeBox
    • Curiosamente, quando pesquisei, nem cheguei a ver essa ferramenta. Eu também estava olhando especialmente a experiência com TypeScript
      Ainda assim, acho que não vou migrar do Zod
    • ArkType é um pesadelo de escrever, e Zod é agradável de escrever
  • Parabéns à equipe do Zod pelo novo lançamento. Mesmo correndo o risco de soar negativo demais, a quantidade de mudanças incompatíveis listadas no guia de migração me dá calafrios
    Para um projeto que depende bastante do Zod, parece ser uma tarefa assustadora, que vai exigir muita concentração e tempo dos desenvolvedores. Isso ressoa especialmente comigo porque já mantive alguns projetos de frontend de 4 a 5 anos no trabalho
    Projetos grandes em React geralmente dependem de muitas bibliotecas e, quando cada uma lança mudanças grandes, ainda mais com documentação insuficiente, tudo fica rapidamente opressor. É uma das partes que mais detesto ao trabalhar com JavaScript, e manter tudo alinhado e funcionando sem problemas parece uma subida sem fim

    • Concordo totalmente. Opero alguns apps grandes em Next.js e, no último ano, tivemos que passar pelas grandes mudanças de cache do Next.js 14 → 15, de Next.js pages → app router, React 18 → 19, Eslint 8 → 9 e Tailwind 3 → 4
      Sinceramente, foi um pesadelo, e pensei que teria sido melhor se tivéssemos feito em Django. Ao contrário do que eu esperava, a migração do Tailwind 3 → 4 foi uma das mais dolorosas
    • É por isso que eles optaram por uma distribuição dupla, com uma edição mini separada. Fica mais fácil fazer uma migração gradual sem mexer no gerenciador de pacotes
      Usuários que não têm interesse na edição mini não precisam se preocupar com essa parte. Mas os benefícios de tree shaking da edição mini eram grandes demais e estavam estimulando o desenvolvimento de alternativas; o Zod precisava aceitar isso ou definhar
    • É só usar um LLM
  • Como desenvolvedor full-stack que opera diretamente um SaaS em produção com milhares de usuários, às vezes percebo com satisfação quantos problemas simplesmente não conheço por ter decidido não criar uma SPA nem usar frameworks JS de frontend
    Nunca nem pensei que algo como Zod/ArkType fosse necessário, ouvi falar pela primeira vez agora e não tenho uso para isso
    É surpreendente a quantidade de esforço, complexidade e ferramentas envolvidas em criar uma SPA. Quando você decide não criar uma SPA, toda uma categoria de problemas simplesmente deixa de existir. Em vez disso, usa o navegador como ele foi originalmente projetado, com recarregamentos completos de página e foco no desenvolvimento de backend, adicionando reatividade ocasionalmente com frameworks exclusivos de backend, como Laravel Livewire
    Tudo fica simples, de controle de acesso a validação e gerenciamento de estado. O app é rápido, responsivo, moderno, amigável para SEO e atende milhares de pessoas em produção

    • Em dois projetos grandes com mais de 5 equipes trabalhando juntas, usamos Zod e Protobuf para permitir uma boa evolução de schemas. Mesmo em um frontend leve, faz sentido usar algo no backend para validar schemas
      No fim, existe um schema em algum lugar. Ele pode ser definido no sistema de banco de dados ou nos modelos do ORM. Mas, em projetos grandes, colocar o schema no sistema de banco de dados ou no ORM pode criar problemas muito difíceis, então usamos Zod e Protobuf. Também acho que o Protobuf poderia ser totalmente substituído por Zod ou algo parecido
      O escândalo do Post Office britânico envolveu um sistema de TI chamado Horizon: https://en.wikipedia.org/wiki/British_Post_Office_scandal
      Lendo os detalhes, parece que uma validação de schema como a do Zod poderia ter ajudado a impedir esse escândalo. O apêndice técnico dos documentos judiciais da ação coletiva também menciona a ausência de uso de schemas: https://en.wikipedia.org/wiki/Bates_%26_Others_v_Post_Office...
    • Zod não tem relação com SPA e não é uma ferramenta exclusiva de frontend. Você não faz validação de entrada no código?
    • Se você fechar os olhos, uma categoria inteira de problemas também pode deixar de existir
    • Fiquei curioso sobre como você faz validação do lado do servidor
      Do jeito que está dizendo, parece que você usa um monte de if defensivo. Ou, pior, talvez dependa apenas da validação de formulários HTML do lado do cliente
    • Temos um monte de schemas Zod usados só no backend como parte do nosso pipeline de dados. Então não parece uma ferramenta que existe apenas para resolver problemas de SPA
  • Não sou especialista, então falo com cautela, mas achei que JSON Schema, por ser baseado em esquemas, poderia ser uma boa escolha porque permite implementar validadores também em linguagens que não sejam TypeScript
    https://ajv.js.org é uma dessas bibliotecas de JSON Schema. Fico curioso para saber como ela se compara ao Zod

    • Zod não é uma ferramenta apenas para validação de JSON. Ele consegue validar objetos que não podem ser representados em JSON sem transformação, como datas ou instâncias de classes
      Se quiser, também pode ser usado como conversor para JSON. Por exemplo, é possível escrever um schema que recebe uma string, valida se ela é uma string de data ISO e produz um objeto Date
    • O Zod 4 oferece suporte nativo à conversão de schemas do Zod para JSON Schema. Antes, isso já era possível com bibliotecas de terceiros
      A diferença importante está no pré-processamento e no refine. No Zod, você pode fornecer callbacks antes da validação, o que é muito útil, mas não pode ser representado em JSON. Por exemplo, antes de validar uma data, converter MM/DD/YYYY para DD/MM/YYYY é algo mais útil com frequência do que parece
    • Nesses casos, JSON Schema é uma boa escolha, e TypeBox é uma forma razoável de gerá-lo
      Para validação, é possível usar o AJV ou o próprio sistema de validação de schemas do TypeBox. Este último é muito mais rápido, mas só oferece suporte síncrono, enquanto o AJV tem opções de validação assíncrona, como checagens em banco de dados
    • Para validação entre linguagens, JSON Schema é o caminho certo. Ao envolvê-lo com OpenAPI, você ainda ganha uma documentação de API decente de graça
  • A reação negativa em torno deste tema é surpreendente
    Testei uma versão inicial do Zod v4 e gostei da nova API, mas fiquei muito preocupado com como seria o caminho de migração. Cheguei até a pensar em sugerir que fosse publicado com um nome de pacote totalmente novo
    Mas a abordagem do autor é inteligente. Ela permite que pessoas como eu adotem a v4 imediatamente sem esperar que todas as dependências sejam atualizadas

    • É um bom caminho. Em algo como validação, não há como lidar com uma migração do tipo tudo ou nada
  • Eu tinha acabado de começar a adotar o Zod em um projeto novo, e não poderia haver momento melhor
    Pelo que vejo agora, parece que haveria muita coisa para mudar para migrar para a v4