Reputation: 26
Based on my types and schemas, I need to have conditional schema which helps me to returns its keys based on select gender, but It does not work correctly.
yup: 1.4.0
export enum PersonGender {
Male = "male",
Female = "female",
}
export const genderValues = Object.values(PersonGender);
type PersonBase = {
name: string;
family: string;
age: number;
gender: PersonGender;
};
type FemalePerson = {
characters: string[];
};
type MalePerson = {
activities: string[];
};
export type Person = PersonBase & (MalePerson | FemalePerson);
export const baseSchema: yup.ObjectSchema<PersonBase> = yup.object().shape({
name: yup.string().required(),
family: yup.string().required(),
age: yup.number().required(),
gender: yup
.string()
.oneOf(genderValues)
.required()
.default(PersonGender.Male),
});
export const maleSchema: yup.ObjectSchema<MalePerson> = yup.object().shape({
activities: yup.array().of(yup.string().required()).min(1).required(),
});
export const femaleSchema: yup.ObjectSchema<FemalePerson> = yup.object().shape({
characters: yup.array().of(yup.string().required()).min(1).required(),
});
export const personSchema = yup.lazy((value) => {
switch (value.gender) {
case PersonGender.Male:
return baseSchema.concat(maleSchema);
case PersonGender.Female:
return baseSchema.concat(femaleSchema);
default:
return baseSchema;
}
});
export type PersonSchemaForm = yup.InferType<typeof personSchema>;
type of PersonSchemaForm is not the same as I need to have like Person
Upvotes: 0
Views: 38
Reputation: 62694
yup is inferring PersonBase
as the result of that schema, because you return baseSchema
on it's own in the default case. You can think of the inferred type as being (PersonBase & MalePerson) | (PersonBase & FemalePerson) | (PersonBase)
corresponding to the three different return
s. This type simplifies to PersonBase
.
If you instead only ever return baseSchema.concat(maleSchema)
or baseSchema.concat(femaleSchema)
, then the inferred type is equivalent to Person
.
export const personSchema = yup.lazy((value) => {
switch (value.gender) {
default: // Male is the default value for gender in baseSchema
case PersonGender.Male:
return baseSchema.concat(maleSchema);
case PersonGender.Female:
return baseSchema.concat(femaleSchema);
}
});
Upvotes: 0