I am trying to achieve the following behavior.
export const NotificationDataSchema = z.object({
type: z.string(),
data: z.object({}),
});
export const LikesMilestoneSchema = NotificationDataSchema.extend({
type: z.literal('LikesMilestone'),
data: z.object({
count: z.number(),
});
});
export const NewFollowerSchema = NotificationDataSchema.extend({
type: z.literal('NewFollower'),
// data: z.object({
// age: z.number(),
// })
});
And I want NewFollowerSchema
to show Error because it doesn't define data
similar to how interface and classes interact, is that possible?
My end goal is to create:
export const NotificationData = z.union([
LikesMilestoneSchema,
NewFollowerSchema,
]);
export const NotificationSchema = z.object({
id: z.string(),
isRead: z.boolean(),
date: z.date(),
data: NotificationData
});
So I could send it as a merged list to the frontend where it will be parsed. But can Zod enforce a subschema to define all fields?
I got an answer for it by the creator on github:
export const NotificationBase = z.object({
type: z.string(),
data: z.record(z.string(), z.unknown()),
});
type NotificationBase = z.ZodType<z.infer<typeof NotificationBase>>;
export const LikesMilestoneSchema = z.object({
type: z.literal("LikesMilestone"),
data: z.object({
count: z.number(),
}),
}) satisfies NotificationBase;
export const NewFollowerSchema = z.object({
type: z.literal("NewFollower"),
}) satisfies NotificationBase;
// ^ does not satisfy the expected type 'NotificationDataSchema'.
https://github.com/colinhacks/zod/issues/4654#event-18065855866