So, when I saw this post and read the first few paragraphs, I was filled with dread for having to do yet another major dependency update. Reading of all the improvements- surly the ‘breaking changes’ list must be massive.
Having read the full article, it seems like the breaking changes have been kept within reason. One major improvement that stands out to me is the improved Recursive types support, but there is certainly any number of improvements for others to be excited about.
The thing I enjoyed most is that excitement of the Arthur really shines throughout the whole article. I’m so thankful this library exists and is being lovingly maintained by someone who is genuinely interested in it.
That said, we are slowly phasing out our React frontend for one of our apps page by page and replacing it with what we use over the rest of apps: Phoenix + Liveview. The changeset system for validations has proven itself time and time again to both be fast but also to handle many of the curly validation problems we might have. It also has barely changed since its release.
If you have a disciplined frontend team then you might be able to make it work. They have to be able to ignore the latest shiny thing that has come along, but if you don't then you'll have a team that is busy constantly upgrading to the latest shiny library rather than getting anything done.
v3 didn't last four years. Can we expect much different from v4?
If you're migrating your zod 3 code, I'd migrate to something more stable and long-lived than v4 is likely to be -- unless you want to be going through it all again in a few years (and yet again a few years after that, etc).
I don't blame the maintainers (I assume they don't have a fat support and maintenance contract)
But developers need to go in with their eyes open when it comes to adopting these throw-away libraries and frameworks.
For contrast: My entire company is less than 4 years old and any code from 6 months ago feels old because things (in a business requirements sense) change so fast. Zod lasting 3 years is fine.
Although I do wish v4 came a little sooner because we just started using Zod a few months ago.
In fact, zod is one of the leading forces behind this: https://github.com/standard-schema/standard-schema
A major version increase in four years doesn’t exactly scream “throw-away” to me.
Of course the bigger question here for most is how large are the breaking changes, not if there is a decade between them.
> I don't blame the maintainers (I assume they don't have a fat support and maintenance contract)
What's the implication here?
I don't know of any software that doesn't have these problems. Either you snapshot a thing and never do updates or you continually update it and have things change.
The update causes almost 0 breaking changes. I don't think this classifies as a "throwaway" library.
4 years in JavaScript land is actually pretty long. Zod has a pretty good maintenance record. I don't see how a statement like yours can be made without snark. Calling it a "throw-away" library is pretty brash.
This looks like a good update that sticks to the formula.
A lot of that is going away with better LSP support and better LLM suggestions.
But elixir and LiveView are generally great (I LOVE ecto), but building component frameworks and component communication still feels a bit janky.
Zod is great in terms of API, but a no-go in terms of performance.
We ended up writing babel plugins (https://github.com/gajus/babel-plugin-zod/) and using it along with zod-accelerator, which improves performance, but breaks in various edge-cases.
Edit to add: aha, now I read further in the announcement, looks like @zod/mini may catch up with valibot -- it uses the same function-based design at least, so unused code can be stripped out.
I've been bit by performance issues, and even a few issues where I just couldn't infer types, with some of the more complex schemas I tried to define, especially with multiple .extend() and .omit() calls.
The zod-mini library looks particularly interesting. I don't mind the more functional approach with nested functions rather than chaining. Reminds me of ramda, that library is pretty massive but still easy to tree shake since everything is functional.
Ecto though, I could never figure out how to use. If I could just make SQL queries in an ORM-style I would understand it, but the repositories and auto generated relations and such I couldn't figure out. Do you have any good resources for learning ecto? I didn't find the official docs helpful.
For non-JS developers to get a sense of how long this is, companies have probably migrated from React to Vue to Svelte to Solid and then back to React in this time.
My understanding is that Zod performs synchronous operations to validate the schemas. Something about "using the tool correctly" resonates here. Maybe don’t validate very large and nested schemas frequently and things like that.
But I can’t help but think it is adding another layer of potential footguns that you have to be mindful about. Maybe the benefits outshine the risks in disciplined teams that understand both the tool and the runtime. However I can’t help but think about the less disciplined teams abusing Zod and then wondering why things are slow.
I've actually found a bit of a resurgence in productivity with React on the front-end and Elixir/Absinthe/Ash Framework on the backend. With GraphQL I get fully typed queries, and Ash Framework on the Elixir side helps a ton with removing the boiler plate of code required for GraphQL, since Ash (mostly) generates the schema for me. A bit of a learning curve with Ash, but now that it's clicked, I feel more productive than I did with just Ecto/Contexts/LiveView.
https://www.ash-hq.org - there's a recent PragProg book on it that really helped it click for me.
Your disdain for resume-driven development is fair enough, but it's not like there's a binary choice between Phoenix/LiveView and spinning your wheels chasing the new shiny.
> Zod 4 introduces first-party JSON Schema conversion via z.toJSONSchema().
Different tools. I only use TS but once you add external data to the mix you cannot escape `any` and `unknown` — so what you do is use `as`. Congrats, your types are now useless.
Zod would close that gap as it enforces types on external resources (e.g. `fetch` or `readFile`)
You can write type assertion functions that validate the input is a given shape.
In theory, you'd use these type assertion methods at any API boundaries a single time for external inputs/outputs in a "Parse, Don't Validate" approach to cover your bases.
Either you parse / validate incoming data at an API boundary with a tool like zod, or you do not, and just trust that the data matches the exact shape you expect, opening yourself up to completely unexpected errors / behaviors if it does not.
The latter is probably a decent option if you fully control all components back to front, but if you really value type safety, the former seems like the way to go?
To me it is bending the original tool (JS, async driven, weak typing) to fit a purpose it was not made for (hard typing, synchronous) in detriment of what it is that makes the tool good in the first place (IO performance).
Zod also works just fine async.