.describe() is not wrapping, but creates a "new" _def
Hey there 👋
I've regularly hoped for some kind of "metadata" in zod, but read a lot of discussion about why it's not needed.
In my case, I just need to be able to identify some of my own schemas.
I do this by comparing someSchema._def with mySchema._def, unwrapping optional et al.
Now I noticed that it does not work with descriptions. Digging into the zod code, I found this: https://github.com/colinhacks/zod/blob/086273160e5952ee661a7b9db82fc757f0e68eab/src/types.ts#L499-L505
My feeling is that this means that the ._def will not point to my schema anymore.
What do you think about adding something like unwrap or innerType to describe, too?
Or am I doing something wrong?
Hi, this pattern is very common in zod, the general def type name will be available, might not be what you need but that could be a pointer in the right direction.
Hi, @hco. I'm Dosu, and I'm helping the Zod team manage their backlog. I'm marking this issue as stale.
Issue Summary:
- You raised a concern with the
.describe()method in Zod, which modifies the_defproperty and complicates schema identification. - You proposed adding an
unwraporinnerTypefeature to maintain the original schema reference. - @m10rten responded, noting that your pattern is common in Zod and suggested using the general def type name, though it might not fully meet your needs.
Next Steps:
- Please let us know if this issue is still relevant with the latest version of Zod. If so, feel free to comment to keep the discussion open.
- If there is no further activity, this issue will be automatically closed in 7 days.
Thank you for your understanding and contribution!
You're right that comparing _def (or def in Zod 4) or schema instances isn't reliable after using .describe() or similar methods—these always return a new schema instance, so identity and internal structure change in ways that break such comparisons. This is intentional: metadata like descriptions is stored in a global registry keyed to the schema instance, not inside the schema itself, and Zod methods are immutable by design. See the docs for more on this pattern: metadata and describe.
For robust schema identification, the recommended approach is to use .meta() or the schema registry system introduced in Zod 4. You can attach a unique id or tag as metadata, then look up schemas by that metadata instead of relying on internal structure or reference equality. Example: z.string().meta({ id: "my-unique-schema" }) docs.
If you need to access the original schema after wrappers like .optional() or .nullable(), Zod 4 provides a standardized .unwrap() method for that purpose (discussion). For more advanced introspection, you can also access the public def property in Zod 4 (reference).
Let me know if this helps or if you want a code example! If your question is answered, feel free to close the issue.
To reply, just mention @dosu.
How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other