Closed markgarel17 closed 1 year ago
If you split out the options schemas then this is a much easier problem to solve.
There is no "discriminator" field for the union, so there's no way to programmatically determine the correct scenario for type validation.
I would expect to see something more like this:
const CarOptionsSchema = z.object({
type: z.literal('car'),
giftMessage: z.string().optional(),
isConvertible: z.boolean().optional(),
})
const TruckOptionsSchema = z.object({
type: z.literal('truck'),
giftMessage: z.string().optional(),
hasHugeWheels: z.boolean().optional(),
})
const SuperCarOptionsSchema = z.object({
type: z.literal('superCar'),
giftMessage: z.string().optional(),
isConvertible: z.boolean().optional(),
})
const CarOptionTypesSchema = z.discriminatedUnion('type', [
CarOptionsSchema,
TruckOptionsSchema,
SuperCarOptionsSchema
])
export const CarApiSchema = z.object({
authToken: z.string(),
colour: z.string(),
options: CarOptionTypesSchema.optional(),
})
@grcodemonkey Hey, thank you for the advise. this gave me insight and was able to do in another way.
I should've been more clearer with the title too. to request a function that can merge deep multiple schemas.
VehicleSchema = z.merge([ CarSchema, TruckSchema, SuperCarSchema ])
with the same result as javascript object, and spread operator.
const vehicle = {
...Car,
...Truck,
...SuperCar
}
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.
Requesting to reopen this.
Can't you just use intersection
/schema.and(...)
?
const VehicleSchema = TruckSchema.and(CarSchema).and(SuperCarSchema)
Can't you just use
intersection
/schema.and(...)
?const VehicleSchema = TruckSchema.and(CarSchema).and(SuperCarSchema)
Depends on what you want to achieve:
const s1 = z.object({ id: z.string() })
const s2 = z.object({ id: z.number(), prop: z.string() })
const totalAnd = s1.and(s2) // { id = never }
const totalOr = s1.or(s2) // { id = number | string; prop = string }
const merged = merge(s1, s2) // { id = number; prop = string }
So, question: how would a function merge
look like, that adds props from s2
to s1
, overwriting props in s1
if already present?
One problem is that:
const VehicleSchema = TruckSchema.and(CarSchema).and(SuperCarSchema)
Results in a ZodIntersection
, not a ZodObject
, so I can't use .passthrough()
on it.
Also:
So, question: how would a function merge look like, that adds props from s2 to s1, overwriting props in s1 if already present?
Yes, exactly like:
const merged = {
...s1,
...s2
}
In fact, this works for me:
const VehicleSchema = z.object({
...TruckSchema.shape,
...SuperCarSchema.shape
});
Why is this not supported yet?
I too would like this reopened please
In fact, this works for me:
const VehicleSchema = z.object({ ...TruckSchema.shape, ...SuperCarSchema.shape });
This works in some cases but not In others. It fails to work where you have a more complex zod type such as when using .optional()
for example.
Will be useful, I agree. I was wondering how to do that and I got here.
It fails to work where you have a more complex zod type
Yes it fails for all the features that distinguish zod from its mediocre competitors 😛
I would like to see this as well.
v3.20.6
We got no way to merge the 3 or more schemas into 1 schema.
GiftVehicle.ts file
If we use
merge
, for more than 2 e.g.CarSchema.merge(TruckSchema).merge(SuperCarSchema)
it doesn't copy the deeper
options
correctly. after test, theTruckSchema.options.hasHugeWheels
disappears.union
ordiscriminatedUnion
is not making it due to the way it works. its not merging of object properties.any suggestions? please help thank you...
. . . . .
GiftCar.ts file
GiftTruck.ts file
GiftSuperCar.ts file