Author here, AMA!<p>Regarding the versioning: I wrote a fairly detailed writeup here[0] for those who are interested in the reasons for this approach.<p>Ultimately npm is not designed to handle the situation Zod finds itself in. Zod is subject to a bunch of constraints that virtually no other libraries are subject to. Namely, the are dozens or hundreds of libraries that directly import interfaces/classes from Zod and use them in their own public-facing API.<p>Since these libraries are directly coupled to Zod, they would need to publish a new major version whenever Zod does. That's ultimately reasonable in isolation, but in Zod's case it would trigger a "version avalanche" would just be painful for everyone involved. Selfishly, I suspect it would result in a huge swath of the ecosystem pinning on v3 forever.<p>The approach I ended up using is analogous to what Golang does. In essence a given package never publishes new breaking versions: they just add a new subpath when a new breaking release is made. In the TypeScript ecosystem, this means libraries can configure a single peer dependency on zod@^3.25.0 and support both versions simultaneously by importing what they need from "zod/v3" and "zod/v4". It provides a nice opt-in incremental upgrade path for end-users of Zod too.<p>[0] <a href="https://github.com/colinhacks/zod/issues/4371">https://github.com/colinhacks/zod/issues/4371</a>
> To simplify the migration process both for users and Zod's ecosystem of associated libraries, Zod 4 is being published alongside Zod 3 as part of the zod@3.25 release. [...] import Zod 4 from the "/v4" subpath<p>npm is an absolute disaster of a dependency management system. Peer dependencies are so broken that they had to make v4 pretend it's v3.
I'm curious if anyone here can answer a question I've wondered about for a long time. I've heard Zod might be in the right ballpark, but from reading the documentation, I'm not sure how I would go about it.<p>Say I have a type returned by the server that might have more sophisticated types than the server API can represent. For instance, api/:postid/author returns a User, but it could either be a normal User or an anonymous User, in which case fields like `username`, `location`, etc come back null. So in this case I might want to use a discriminated union to represent my User object. And other objects coming back from other endpoints might also need some type alterations done to them as well. For instance, a User might sometimes have Post[] on them, and if the Post is from a moderator, it might have special attributes, etc - another discriminated union.<p>In the past, I've written functions like normalizeUser() and normalizePost() to solve this, but this quickly becomes really messy. Since different endpoints return different subsets of the User/Post model, I would end up writing like 5 different versions of normalizePost for each endpoint, which seems like a mess.<p>How do people solve this problem?
Zod is a lot better than some of the alternative solutions I've seen. That said, the need for this sort of explicit validation always felt like a failure of where modern web development has taken us. It's so frustrating how full-stack development requires so many ways of describing the same shapes: JS input validation, Swagger for API definition, server-side input validation, ORM for schema conformance, and TypeScript often requiring separate definitions on server and client side. It's so tedious.
Zod 4 looks good but even with their latest improvements, ArkType is still an order of magnitude faster. Sometimes for the sake of backward and syntax compatibility, it is difficult to make something much faster than a fully greenfield newer library. We recently did an analysis of all these types of tools for our project and decided to go with ArkType for partially this reason, the other was TypeScript ergonomics felt nicer.
As a full stack dev that runs their own SaaS with thousands of users in production, sometimes I get a very pleasant reminder of how many problems I am blissfully unaware of just because I decided not to build an SPA or use JS frontend frameworks. It never occurred to me that I need such a thing as Zod/ArkType - first time hearing of it, and I have no use for it.<p>It boggles my mind how much effort and complexity and tooling goes into building an SPA. Entire classes of problems simply don't exist if you choose not to build an SPA. Meanwhile, I use the browser as designed: with full page reloads, backend development only, and occasional reactivity using a backend-only framework like Laravel Livewire. Everything is so simple: from access control to validation to state management. And yes, my app is fast, reactive, modern, SEO friendly, and serves thousands of users in production.
Congratulations to the Zod team on the new release. At the risk of sounding overtly negative, I can't help but shudder when I think about the number of breaking changes outlined in the migration guide. For projects that rely heavily on Zod, it feels like a daunting task ahead—one that will demand a lot of developer attention and time to navigate. Having maintained a few frontend projects that are 4-5 years old at work, I really empathize with them.<p>In my experience, large React projects often depend on a multitude of libraries, and when each one rolls out substantial changes—sometimes with barely any documentation—it can quickly become overwhelming. This is honestly one of my least favorite aspects of working with JavaScript. It just feels like a constant uphill battle to keep everything in sync and functioning smoothly.
I am not an expert here but I had a thought that JSON-Schema might be a good choice because since it's schema based, i can implement the validators in Non-Typescript languages too.<p><a href="https://ajv.js.org" rel="nofollow">https://ajv.js.org</a> is one such JSON Schema library. How does zod compare to this?
Shocked by the negativity around this.<p>I tested early versions of zod v4 and liked the new API, but was very concerned about what will be the migration path. I was even going to suggest to publish under a new package name.<p>But the author's approach is ingenious. It allows for someone like me to start adopting v4 immediately without waiting for every dependency to update.<p>Well done!
I just got started working Zod into a new project. This could not have happened at a better time. I would have needed to change so much ot migrate to v4 based on what I'm seeing.
The versioning approach here is a really interesting compromise — especially in the npm ecosystem where breaking changes ripple out so painfully through transitive dependencies. From a developer ergonomics standpoint though, the shift to zod/v4 imports will definitely create some friction. For teams with IDEs auto-importing from 'zod' and linters enforcing import styles, it might introduce subtle DX issues until workflows are adjusted.<p>That said, the strategy does seem to prioritize ecosystem stability over short-term convenience, which is fair. Would love to see better tooling (maybe even IDE plugins or codemods) to help projects transition cleanly. Really appreciate the thoughtful design behind all of this.
We're currently evaluating both Zod and ArkType as a replacement for earlier JSON schema validations. The thing I can't get over with Zod is the syntax is _so_ different from defining TS types.<p>Are there reasons to go with Zod over ArkType?
Hopefully someone can compare Zod4 to TypeBox.<p>Last I looked, the nice thing about TypeBox was that is _was_ JsonSchema just typed which was nice for interoperability.
> TypeScript-first schema validation with static type inference<p>Is there a comparison guide? Never heard of this before, but I used io-ts and ajv.
One decision that seems dubious to me is the zod/v4-mini import. I suspect that this will actually <i>increase</i> bundle sizes across the ecosystem. The docs specifically say "zod/v4 is still recommended for the majority of use cases", so application developers will use it. Library authors will think to themselves, "but I want to enable my library to be used by those with uncommonly strict bundle size requirements", and so will use that. The net result is that both zod/v4 and zod/v4-mini will be included in the application bundle.<p>I guess this could be mostly avoided if zod/v4 actually a wrapper around zod/v4-mini. Is that the case?
With yet another exciting new release of something reaching the top of HN, I would just like to urge devs to put a description of the project they're actually releasing and a link to the page describing the project in the release announcement.<p>These announcements could be a valuable touchpoint for you to reach a whole new audience, but I can't remember a single one that starts with something like "exciting new release of NAME, the X that does Y for users of Z. Check out the project home page at <a href="https://" rel="nofollow">https://</a> for more."<p>Quite often, the release announcement is a dead end that can't even take me to the project! In this case, the only link is a tiny octocat in the lower left-hand corner, AFAICS.
But how is the below possible - doesn't it need to include most of the TypeScript compiler? Does it compile the type definitions to some kind of validation structure (like how a compiled regex works) and then use just that?<p><pre><code> - Zero external dependencies
- Works in Node.js and all modern browsers
- Tiny: 2kb core bundle (gzipped)</code></pre>
Great job! I love support of json conversion you built-in. However, I find top level string bad choice as it was more verbose before, to have them under string() namespace.
All that text. So, so much text and not one single (maybe there was, but I fell asleep), not one single "Let me tell you what Zod is" paragraph. Lots of "Zod 4 is better than Zod 3" and "Here's what we pulled back, out, in, from Zod 2".
great job on zod. it’s an incredible library. also really excited about the locale errors. finally I can push the zod errors directly to the frontend. would love to take responsibility for the BG locale.
Obligatory shameless plug whenever Zod is posted: if you want similar, but much more minimal schema validation at runtime, with a JSON representation, try Spartan Schema: <a href="https://github.com/ar-nelson/spartan-schema">https://github.com/ar-nelson/spartan-schema</a>
i would use it if there was just 1 normal zod lib not like how it is now: zod and zod mini and who knows what.
I rather use arktype or valibot if i am in browser only.
Seeing an announcement for a new version of some typescript library I've never heard of shoot to the top of the front page makes me feel extremely out of touch with mainstream dev.
Between GraphQL and Zod, there really is no comparison. The latter feels clunky and superfluous by design when the former ecosystem can smoothly provide static TS typings without extra work or schema duplication.