描述
假设我们有以下一组 TypeScript 接口:
// Indexed type for type-specific fields
interface RichTextMap {
text?: { text: string };
equation?: { equation: string };
mention?: { mention: string };
}
// Main RichText interface with indexed types
interface RichTextBase {
type: "text" | "mention" | "equation";
annotations: any;
plain_text: string;
href: string | null;
}
type RichText = RichTextBase & (RichTextMap[RichTextBase["type"]] & {});
RichText
类型应允许对象如下:
const text = {
type: "text",
annotations: {},
plain_text: "",
href: null,
text: { text: "" }
}
const mention = {
type: "mention",
annotations: {},
plain_text: "",
href: null,
mention: { mention: "" }
}
问题陈述
我需要为提到的对象定义
zod
模式。
我对
zod
的理解还有待提高,但到目前为止我已经设法提出以下解决方案:
const RichTextSchema = z
.object({
type: z.enum(["text", "mention", "equation"]),
annotations: z.object({}).passthrough(),
plain_text: z.string(),
href: z.string().url().nullable(),
});
const TextRichTextSchema = RichTextSchema.extend({
text: z.object({ text: z.string() }).optional(),
})
const MentionRichTextSchema = RichTextSchema.extend({
mention: z.object({ mention: z.string() }).optional(),
})
const EquationRichTextSchema = RichTextSchema.extend({
equation: z.object({ equation: z.string() }).optional(),
})
现在,这种方法的问题是我正在创建三种不同的模式,并且必须弄清楚在运行时调用哪一个。虽然接口类型足够通用,可以在单一类型下容纳不同的对象。
问题:我想知道是否有办法更改
RichTextSchema
,以便能够针对上述接口类型进行验证。本质上,只保留一个模式对象来验证示例中的不同对象。
您似乎正在寻找的是 Zod 中受歧视工会案例的确切用途。
这是一个基于您的案例的示例:
import { z } from "zod";
const RichTextBaseSchema = z.object({
annotations: z.object({}).passthrough(),
plain_text: z.string(),
href: z.string().url().nullable(),
});
const RichTextSchema = z.discriminatedUnion("type", [
RichTextBaseSchema.extend({
type: z.literal("text"),
text: z.object({
text: z.string()
}),
}),
RichTextBaseSchema.extend({
type: z.literal("mention"),
mention: z.object({
mention: z.string()
}),
}),
RichTextBaseSchema.extend({
type: z.literal("equation"),
equation: z.object({
equation: z.string()
}),
}),
]);
type RichText = z.infer<typeof RichTextSchema>;