Published: May 5, 2025
46
117
2.2k

whoa. I just found a way to properly infer recursive types in z.object() — no casting, no z.lazy(), no scopes/registries, no special syntax. i've been trying to do this for literally years

Image in tweet by colinhacks/zod

here's mutual recursion working

Image in tweet by colinhacks/zod

works with z.toJSONSchema 💅

Image in tweet by colinhacks/zod

this development kind of negates the raison d'être for `z.interface()`. it has been removed in the most recent betas. i've never been happier to delete 3k LOC.

Image in tweet by colinhacks/zod

"but what about key-optional versus value-optional properties?" this was one of two stated reasons for the introduction of z.interface() in the original Zod 4 beta announcement (the other being recursive type support)

Image in tweet by colinhacks/zod

at that point I was trying to steer people towards z.interface() so I chose de-emphasized a minor change coming in Zod 4... Zod now treats `.optional()` slightly differently than `.or(z.undefined()` — which means both kinds of optionality can be represented in z.object() 🍾

Image in tweet by colinhacks/zod

Share this thread

Read on Twitter

View original thread

Navigate thread

1/6