如何将递归判别联合类型转换为Zod Schema?
解决Zod递归判别联合类型的初始化循环引用错误
你遇到的错误源于Schema初始化时的循环引用:GroupSchema中提前引用了未定义的ComponentSchema,而ComponentSchema又依赖GroupSchema,导致初始化顺序冲突。处理这种递归结构的判别联合类型,需要用Zod的lazy()方法延迟Schema解析。
原TypeScript递归类型
interface TextInput { type: 'text-input' } interface Group { type: 'group'; components: AppComponent[] } type AppComponent = TextInput | Group const component: AppComponent = { type: 'group', components: [{ type: 'text-input' }], }
正确的Zod实现方案
import { z } from 'zod'; // 先定义无递归依赖的TextInput Schema const TextInputSchema = z.object({ type: z.literal('text-input'), }); // 使用z.lazy()延迟引用ComponentSchema,避免初始化阶段的循环依赖 const GroupSchema = z.object({ type: z.literal('group'), components: z.array(z.lazy(() => ComponentSchema)), }); // 最后定义判别联合Schema const ComponentSchema = z.discriminatedUnion('type', [TextInputSchema, GroupSchema]); // 导出对应的TypeScript类型(可选) export type AppComponent = z.infer<typeof ComponentSchema>;
代码说明
z.lazy(() => ComponentSchema):该方法会在Zod实际执行校验逻辑时才去获取ComponentSchema的定义,绕开了初始化阶段的循环引用问题。- 保留判别联合逻辑:依然通过
type字段作为判别符,Zod会自动根据type值匹配对应的Schema完成校验。
测试验证
用原示例数据校验可确认逻辑正常:
const testComponent = { type: 'group', components: [{ type: 'text-input' }], }; const validationResult = ComponentSchema.safeParse(testComponent); console.log(validationResult.success); // 输出 true
内容的提问来源于stack exchange,提问作者feerlay
相关产品推荐
相关产品推荐

