Replies: 1 comment
-
I don't think there's a straightforward way to do this. The closest to the basic TS types is const eitherAOrBSchema = z.union([
z.object({
a: z.string(),
b: z.never(),
}),
z.object({
a: z.never(),
b: z.number(),
}),
]);
/*
type Type = {
a: string;
b: never;
} | {
a: never;
b: number;
}
*/
type Type = z.input<typeof eitherAOrBSchema>; However, this doesn't work because the type that is The other alternative is like this, which doesn't work either. const eitherAOrBSchema = z.union([
z.object({
a: z.string(),
b: z.never().optional(),
}),
z.object({
a: z.never().optional(),
b: z.number(),
}),
]);
/*
type Type = {
a: string;
b?: undefined;
} | {
a?: undefined;
b: number;
}
*/
type Type = z.input<typeof eitherAOrBSchema>; As mentioned in #3186, Zod doesn't differentiate between optional properties and properties that should be undefined. I think the only solution right now is to use the type EitherAOrB =
{
a: string;
b?: never;
} | {
a?: never;
b: number;
};
const eitherAOrBSchema = z
.object({
a: z.string().optional(),
b: z.number().optional(),
})
.superRefine((data, ctx): data is EitherAOrB => {
if ("a" in data && "b" in data) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Either a or b can be defined, but not both.",
});
} else if (!("a" in data || "b" in data)) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: "Either a or b must be defined.",
});
}
});
type InputType = z.input<typeof eitherAOrBSchema>;
type OutputType = z.output<typeof eitherAOrBSchema>; |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
In TypeScript I can create an XOR type using a union type like
This allows me to have types where when e.g.
a
is set, I am not allowed to also setb
.I tried to do this with zod:
However, like this, TypeScript doesn't care if I set both properties on an EitherAOrB.
I found this discussion where a solution for parsing was found, however this does not deal with inferring a type.
Is this possible to achieve?
Beta Was this translation helpful? Give feedback.
All reactions