You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zod中扩展类型联合解析为基础类型的问题求助

问题原因与解决方案

核心原因

Zod的联合类型(z.union)是按顺序尝试匹配Schema的:只要数据通过了某一个Schema的验证,就会直接用该Schema解析,不会继续检查后续的Schema。

你的场景中,typeA是typeB的子集——所有符合typeB的数据都满足typeA的结构要求,这就导致了两个问题:

  • 当typeA排在联合列表前面时,typeB的数据会被typeA优先匹配,而Zod的object默认会剥离未定义的字段,所以extraProp会被移除。
  • 当typeB排在前面时,错误的extraProp(比如数字4)会让typeB验证失败,随后自动fallback到typeA,同样会剥离错误字段,不会触发预期的报错。

解决方案

方案1:让typeA严格拒绝额外字段

给typeA添加strict()方法,这样当数据包含extraProp这类未定义字段时,typeA会验证失败,转而尝试匹配typeB:

const typeA = z.object({ prop: z.string() }).strict();

const typeB = typeA.extend({
  extraProp: z.boolean(),
});

const schema = z.array(z.union([typeA, typeB]));

// 正确解析typeB数据
schema.parse([{ prop: 'foo', extraProp: true }]); 
// 输出:[{ "prop": "foo", "extraProp": true }]

// 错误数据触发报错
schema.parse([{ prop: 'foo', extraProp: 4 }]); 
// 抛出ZodError:extraProp必须是布尔值

方案2:使用区分式联合(z.discriminatedUnion)

如果你的数据可以添加一个用来区分类型的字段(比如type),推荐使用discriminatedUnion,它会直接根据区分字段匹配对应的Schema,完全避免顺序问题:

const typeA = z.object({
  type: z.literal('A'),
  prop: z.string(),
});

const typeB = z.object({
  type: z.literal('B'),
  prop: z.string(),
  extraProp: z.boolean(),
});

const schema = z.array(z.discriminatedUnion('type', [typeA, typeB]));

// 正确解析typeB数据
schema.parse([{ type: 'B', prop: 'foo', extraProp: true }]); 

// 错误数据触发报错
schema.parse([{ type: 'B', prop: 'foo', extraProp: 4 }]); 
// 抛出ZodError:extraProp类型错误

内容的提问来源于stack exchange,提问作者fZab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:57:27