zod: ZodObject that are `.refine` or `.superRefine` returns a ZodEffects type
Zod version 3.21.4
Problem
Using .refine() or .superRefine() on ZodObject (z.object()) prevents the use of .shape or .merge() method as the returned type is a ZodEffects and not a ZodObject.
Example
const schema1 = z.object({ foo: z.string() }) // = type ZodObject
const schema2 = z.object({
bar: z.string(),
attributeRelatedToBar: z.string(),
}).superRefine(handleSchema2Errors) // = type ZodEffects
/**
* Impossible because `.merge` expect `schema2` to be type of `ZodObject` instead of `ZodEffects`:
* TS2352: Conversion of type 'ZodEffects […] to type 'ZodObject ' may be a mistake because
* neither type sufficiently overlaps with the other.
* If this was intentional, convert the expression to 'unknown' first.
*/
const finalSchema = schema1.merge(schema2)
/**
* Same error with `.shape` that expect a `ZodObject` instead of `ZodEffects`:
* TS2339: Property 'shape' does not exist on type 'ZodEffects'.
*/
schema2.shape.bar
schema2.shape.attributeRelatedToBar
Expected behavior
Using .superRefine() or .refine() on z.object() should return a ZodObject type
– or –
.merge() & .shape should be functional on ZodEffects applied to a ZodObject.
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 53
- Comments: 24
Is this what you are looking for?
If you found my answer satisfactory, please consider supporting me. Even a small amount is greatly appreciated. Thanks friend! 🙏 https://github.com/sponsors/JacobWeisenburger
This unfortunately make complex types into a real pain to use with this library
It also prevents the use of
discrimatedUnion.You should use
.andsee https://github.com/colinhacks/zod/issues/1147This is the expected behavior. The unexpected behavior needs to be documented.
I don’t see how
.andis a replacement for calling refine or superRefine on a whole object to be able to access the properties in validation logic.Up on this topic ? Issue still the same with zod
^3.22.4@thibaultleouay Thank you. But I don’t see
.andas a solution but as a workaround 😄.Same issue here! I have pretty large object schemas that need to be changed altogether, and I am trying to use functions similar to the following for that.
the issue is that the date validation does’t get picked up because it is using
refine()but I cannot use
z.ZodEffectsbecause then everything that isn’t adate()validation is also going to get triggered.The same goes if I use
and(), since the outcome is that everything becomes an intersection instead of an effect.Is there any way for me to pick up the validation type even after using refine? I am fine with any workarounds for now
Seems that
.omit()isn’t allowed after a.refine(), which is not useful.Making these changes to the repo fixes the core issue https://github.com/colinhacks/zod/compare/master...Dan503:zod:2474-refine-not-returning-correct-types-info
I haven’t made a PR because it still has type conflict errors and is failing a lot of unit tests.
@oyatek It breaks the composition
Example 1
Let’s imagine that we have a reusable type utility:
And you want to reuse it in multiple places:
The current approach makes it difficult to implement a schema utility and, in some ways, breaks schema encapsulation.
Example 2
You have some schema that represent API endpoint
But for the API POST method, you want to modify your schema and omit
idpropYou may have noticed that there is an issue with the current implementation of your application. Specifically, you may need to refine some of the schemas during the latest stage of development. However, the proposed solution would require you to rewrite a large portion of your application.
This isn’t only an issue for the object schema. It is an issue for all schemas.
.refine()and.superRefine()should return a schema that has all the same properties as what was there before it was used.I came across as well. How to fix this? By fix I mean that I want to keep the chaining of the schema, like merging another schema or do anything else.
If refine shouldn’t mean to support this, what does so?
How is what I gave you not “fully functional”?
I used
superRefinein my solution. ✅I fail to see the problem that you are talking about. Please explain more.
Considering Zod doesn’t release very often, your choices are to use a workaround in the mean time or wait for your problem to be addressed and then wait for it to be released. Based on how things have been going, that could be 6 months. If that’s ok for you, then great.
Generally when someone tries to help you, it’s not the best approach to belittle their efforts. But thanks.
The schema is a validation schema and must be fully functional. So in my context, this is a necessity to have a
refine|superRefineto make the validation work.There is a problem between
ZodObjectandZodEffectstype that needs to be fixed. I don’t want to use a workaround.Even if I wanted to use a workaround, the solution you suggested would have been easy to find.