cannot figure out how to create a schema from the discriminator key of a discriminated union #3032
-
Howdy, all. First off, thanks for the amazing library. We really enjoy using it here at the office. Context: We'd like to create a Zod schema that represents the set of values used as discriminator keys in a discriminated union. Given this code: const Result = z.discriminatedUnion("status", [
z.object({ status: z.literal("success"), data: z.string() }),
z.object({ status: z.literal("failed"), error: z.instanceof(Error) }),
]);
type Result = z.infer<typeof Result>; We'd like to produce a new schema: const ResultStatus = Result.shape.type // does not compile
type ResultStatus = z.infer<typeof ResultStatus>; There is no Thanks in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 12 replies
-
maybe this will solve the query @laser const SuccessResult = z.object({ status: z.literal('success'), data: z.string() });
const FailedResult = z.object({ status: z.literal('failed'), error: z.instanceof(Error) });
const Result = z.discriminatedUnion('status', [SuccessResult, FailedResult]);
type SuccessResult = z.infer<typeof SuccessResult>;
type FailedResult = z.infer<typeof FailedResult>;
type Result = z.infer<typeof Result>;
const discriminator = Result.discriminator; // const discriminator: "status"
const options = Result.options; // const options: [SuccessResult, FailedResult]
const optionsMap = Result.optionsMap; // const optionsMap: Map{'success' => SuccessResult, 'failed' => FailedResult} |
Beta Was this translation helpful? Give feedback.
-
Alright @laser , in that case you can do type Result = z.infer<typeof Result>;
type discriminator = typeof Result.discriminator;
type options = typeof Result.options;
type ResultStatusSchema = options[number] extends z.ZodObject<{ [key in discriminator]: infer T } & z.ZodRawShape, z.UnknownKeysParam, z.ZodTypeAny>
? T
: never;
type ResultStatus = z.infer<ResultStatusSchema>;
function printStatus(x: ResultStatus) {
console.log(x);
}
printStatus('success'); // ok
printStatus('flarp'); // I'd like this to be rejected by the type checker |
Beta Was this translation helpful? Give feedback.
-
Is this what you are looking for? const ResultStatusSchema = z.enum( [ 'success', 'failed' ] )
type ResultStatusType = z.infer<typeof ResultStatusSchema>
// type ResultStatusType = 'success' | 'failed'
const ResultSchema = z.discriminatedUnion( 'status', [
z.object( { status: ResultStatusSchema.extract( [ 'success' ] ), data: z.string() } ),
z.object( { status: ResultStatusSchema.extract( [ 'failed' ] ), error: z.instanceof( Error ) } ),
] )
type ResultType = z.infer<typeof ResultSchema>
// type ResultType = {
// status: 'success'
// data: string
// } | {
// status: 'failed'
// error: Error
// } If you found my answer satisfactory, please consider supporting me. Even a small amount is greatly appreciated. Thanks friend! 🙏 |
Beta Was this translation helpful? Give feedback.
-
Damn i wished this have been in the docs, I searched for it ages thanks @JacobWeisenburger |
Beta Was this translation helpful? Give feedback.
Is this what you are looking for?
If you found my answer satisfactory, please consider supporting me. E…