Help Needed: Hard time understanding Discriminated Union #957
Replies: 2 comments 1 reply
-
I'm not sure I understand your final const schema = z.union([baseSchema, workLocationSchema, workStatusSchema]) I think you're trying to make an intersection where different parts of the resultant model are defined by unions rather than by intersections. Does this work: const schema = z.intersection([workLocationSchema, workStatusSchema]); —? I would also avoid doing destructuring in your const onSubmit = async (formData: FormData) => {
switch (formData.workStatus) {
case Work_Status_Types_Enum.FullTime:
// TypeScript knows we are in that case now
break;
}
}; (or use Feel free to submit a CodeSandbox if you need a bit more assistance with this and I can help when I get a chance. You can use my Zod Template to help get a minimal repro. |
Beta Was this translation helpful? Give feedback.
-
Hi @scotttrinh, Sorry for the long silence, I had some health issues. I went ahead and created this codesandbox: https://codesandbox.io/s/zod-union-types-ez6yu I've updated the schema but it's still not working, this is what I have now: const baseSchema = z.object({
workStatus: workStatusEnumSchema,
workLocationType: workLocationEnumSchema,
vacationDuration: workVacationEnumSchema,
address: z.string(),
latitude: z.number(),
longitude: z.number(),
drivingToWork: z.boolean(),
occasionallyTravelOffice: z.boolean(),
relocateForWork: z.boolean(),
visaSponsorShip: z.array(visaSponsorshipSchema),
spokenLanguages: z.array(optionSchema),
})
const fullTimeSchema = baseSchema.extend({
workStatus: z.literal(Work_Status_Types_Enum.FullTime),
fullTimeCompensation: z.string().nonempty({
message: 'fullTimeSchema field required',
}),
contractCompensation: z.string().length(0, { message: 'contractCompensation must be empty' }),
})
const contractSchema = baseSchema.extend({
workStatus: z.literal(Work_Status_Types_Enum.Contract),
contractCompensation: z.string().nonempty({
message: 'contract type required',
}),
fullTimeCompensation: z.string().length(0, { message: 'fullTimeCompensation must be empty' }),
})
const fullTimeContractSchema = baseSchema.extend({
workStatus: z.literal(Work_Status_Types_Enum.FullTimeOrContract),
contractCompensation: z.string().nonempty({
message: 'contractCompensation required',
}),
fullTimeCompensation: z.string().nonempty({
message: 'fullTime required',
}),
})
const workStatusSchema = z.union([fullTimeSchema, contractSchema, fullTimeContractSchema])
const flexibleSchema = baseSchema.extend({
workLocationType: z.literal(Work_Location_Types_Enum.Flexible),
acceptableTravelTime: z.string().nonempty({
message: 'acceptableTravelTime required',
}),
})
const remoteSchema = baseSchema.extend({
workLocationType: z.literal(Work_Location_Types_Enum.Remote),
acceptableTravelTime: z.string().length(0, { message: 'acceptableTravelTime must be empty' }),
})
const workLocationSchema = z.union([flexibleSchema, remoteSchema])
const schema = z.intersection(workLocationSchema, workStatusSchema) I'm not destructuring Here are a couple of scenarios: I select What kind of work are you looking for, How many weeks of vacation per year are you looking for and Work site preferences (which are all 3 enums) without filling any other field: Another example with different selections for What kind of work are you looking for and Work site preferences I'm not sure why, no mater which option I chose in What kind of work are you looking for and Work site preferences, I'm always receiving an error that is expect another option. I don't know what I'm missing or doing wrong. I've tried many things but none of them worked. I've noticed that I was getting errors on invalid types but this is because I was initializing input fields with an empty string Any help would be greatly appreciated :) Thank you |
Beta Was this translation helpful? Give feedback.
-
I'm having a hard time understanding how discriminated union work.
I have this schema bellow and I have a couple of conditions:
One is for the
workStatus
this is required. The user has 3 options, "Full Time", "Contract" and "Both"Now based on what the user selects we must display the appropriate fields
=> User selects "Full Time" then we need to request for
fullTimeCompensation
andcontractCompensation
should be undefined=> User selects 'Contract" then we need to request for 'contractCompensation
and
fullTimeCompensationshould be undefined => User selects 'Both" then we need to request for
fullTimeCompensationand 'contractCompensation
The other condition is
workLocationType
, this is a required field and the user has two options, either "Remote" or "Flexible"If the user selects "Flexible" we need to as for field
acceptableTravelTime
, if user selects "Remote" thenacceptableTravelTime
should be undefined.This is how I've defined my schemas
At this point I have no errors in the schema nor in the default values.
However, in my
onSubmit
function which is defined as follow:But this clearly doesn't work. If a user selects 'Full Time" then I get an error "Expeted 'CONTRACT', received 'FULL_TIME'", and in
fullTimeCompensation
if the user enters a value he get's an error "Expected undefined, received 'string'". Same thing if the user selects 'CONTRACT' and same behaviour forworkLocationType
if user selects something else other than "REMOTE" he will get the same error.I'm not sure how to create the schema for my use case :(
Any help would be greatly appreciated.
Beta Was this translation helpful? Give feedback.
All reactions