zod icon indicating copy to clipboard operation
zod copied to clipboard

.describe() is not wrapping, but creates a "new" _def

Open hco opened this issue 1 year ago • 1 comments

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?

hco avatar Nov 04 '24 12:11 hco

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 about the .describe() method in Zod altering the _def property of schemas.
  • This alteration complicates your method of schema identification through _def comparison.
  • You proposed adding an unwrap or innerType feature to maintain the original schema reference.
  • You are seeking feedback on whether your approach to schema identification is flawed.
  • There has been no activity or comments from other users or maintainers on this issue yet.

Next Steps:

  • Please let us know if this issue is still relevant to the latest version of the Zod repository. If so, you can keep the discussion open by commenting on the issue.
  • Otherwise, this issue will be automatically closed in 7 days.

Thank you for your understanding and contribution!

dosubot[bot] avatar Jun 19 '25 16:06 dosubot[bot]

You're correct: in Zod 4, .describe() creates a new schema instance with a new _def—it doesn't wrap the original schema, so identity checks like schemaA._def === schemaB._def will fail after using .describe() or similar methods. This is intentional and applies to other schema-transforming methods as well. Comparing _def is not a reliable way to identify schemas, especially after chaining methods like .describe(), .meta(), .optional(), etc. source

For schema identification or attaching metadata, the recommended approach is to use .meta({ id: "your-identifier" }) and retrieve it with .meta() when needed. Metadata is always tied to a specific schema instance, so if you transform a schema, you'll need to reapply or merge metadata as needed. source

There is a standardized .unwrap() method in Zod 4, but it only applies to certain wrappers like .optional(), .nullable(), or .default()—not to .describe() or .meta(), since those don't wrap but clone the schema. There's no general-purpose unwrap or innerType for all schema layers. source

If you want to reliably identify schemas, attaching an id via .meta() is the best practice. If you have a more complex use case, feel free to share a minimal, runnable snippet and I can help dig deeper.

If this answers your question, please close the issue!

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Join Discord Share on X

dosubot[bot] avatar Jul 21 '25 22:07 dosubot[bot]