How do you even migrate incrementally? why keep both old and new code together like a Frankeinstein project? Especially on a codebase you own. It's a library, not a platform.
> why keep both old and new code together like a Frankeinstein project?
It seems like Zod is a library that provides schema to your (domain) objects in JS/TS projects, so if you're all-in with this library, it's probably a base-layer for a ton of stuff in the entire codebase.
Now imagine that the codebase is worked on by multiple parties, in different areas, and you're dealing with 100K-1M lines of code. Realistically, you can't coordinate such a huge change with just one "Migrated to Zod 4" commit and call it a day, and you most likely want to do it in pieces.
I'm not convinced publishing V4 as version 3 on npm is the best way of achieving this, but to make that process easier seems to be the goal of that as far as I understand.
If it's part of your core domain, I'd say that one of the reasons you want the feature set and the API to be as stable as possible. And your core domain should probably be isolated from the things that depends on it in such way that only business logic ripples out.
One of the strange things from the NPM/JS culture is the focus to write everything in one language leading to everyone forgetting about modularization and principles like SOLID. We link everything together with strange mechanisms for "DX", which really means "make it easy to write the first version, maintenance be damned".
This comment feels very detached from reality. Migrating core dependencies in large projects is always cumbersome. One universal truth is that you can make complex tasks easy by breaking it up into small pieces. Providing a sensible forward migration path like what Zod does causes 0 harm and makes everyone's life easier. This has absolutely nothing to do with "NPM/JS" culture, whatever that means.
You use Zod to define all the schemas and types used in "your core domain". It is the base layer tool of your business logic and models, and for defining your interfaces. And yes it makes it possible to share all of this between the frontend and backend, which is a tremendous improvement in both correctness and in development productivity.
You don't get anything remotely like this in any other backend frontend combo.
I get the wish to have that, but IMO, it's a flawed approach. The frontend and the backend are generally different domains. Initially, their model may look alike, but they will probably differs during the lifetime of the project as they serve different needs. That's why the shape of the data stored in the DB differs from the one involved in business logic, which differs from the DTOs, which can differs from the objects involved in the presentation.
In simple applications, you can get away with defining a single schema for all, but it helps with keeping in mind that you may have to design a better data shape for some logic.
> The frontend and the backend are generally different domains
It is not a flawed approach, it's an important need for most web apps. Zod is a validation library, the whole purpose of is to define structures that can safely be shared across domains.
The point is that somewhere, you need to chuck bytes over the network and someone needs to receive them.
If the teams working on the two are different, or even if the expertise level is uneven, something like a typed serialization library is a great boon.
At work, I maintain a Haskell-like programming language which spits out JSON representations of charts over OLAP queries. I’m the only one who knows the language extensively, but everyone is expected to do work with the JSON I push. If I serialize something incorrectly, or if someone else mistypes the frontend JSON response definition, we’re in for a world of pain.
Needless to say, I’ll be adding something like Zod to make that situation safer for everyone.
> If the teams working on the two are different, or even if the expertise level is uneven, something like a typed serialization library is a great boon.
You don't even need that, I use typed serialization on both sides when talking to myself. How else do I guarantee the shape of what I send and receive? I want my codebase to scream at me if I ever mess it up.
This is not done for Zod's benefit. It's done for the benefit of libraries that depend on Zod, and the users of those libraries. If a library wants to add "incremental" support for Zod4 (that is, without dropping support for Zod 3 and publishing a new major), they need access to types (and possibly runtime code) from both libraries to do so in a sound way. I detail a number of other approaches for achieving this here[0] and why they ultimately fall short. Ultimately npm wasn't designed for this particular set of circumstances.
Yeah, importing two versions could allow you to pass v3 objects to v4 methods and vice versa, and that seems like an extremely bad idea (if it would even type-check / run).