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

Zod如何基于两个鉴别字段实现payload类型区分?

基于Zod中多字段组合鉴别payload类型的解决方案

Zod的discriminatedUnion确实仅支持单个鉴别字段,但可以通过以下两种方案实现多字段组合的payload类型鉴别:

方案一:定义组合对应的完整Schema并合并为Union

先修正并完善基础枚举与各组合的Schema:

enum Action {
  CREATE = 'create'
}

enum ObjectType {
  Potatoe = 'potatoe',
  Tomatoe = 'tomatoe'
}

// 定义每个(action, objectType)组合对应的完整对象Schema
const CreatePotatoSchema = z.object({
  action: z.literal(Action.CREATE),
  objectType: z.literal(ObjectType.Potatoe),
  payload: z.object({
    weight: z.number() // 对应Potatoe的CREATE操作payload结构
  })
});

const CreateTomatoSchema = z.object({
  action: z.literal(Action.CREATE),
  objectType: z.literal(ObjectType.Tomatoe),
  payload: z.object({
    ripeness: z.string() // 对应Tomatoe的CREATE操作payload结构
  })
});

// 合并为Union Schema
export const TestSchema = z.union([CreatePotatoSchema, CreateTomatoSchema]);

这种方式直接为每个字段组合定义完整的Schema,Zod会自动匹配对应的结构,同时正确推断payload的类型。

方案二:派生虚拟鉴别字段(适合多组合场景)

如果字段组合数量较多,可以通过派生虚拟鉴别字段的方式复用discriminatedUnion:

enum Action {
  CREATE = 'create'
}

enum ObjectType {
  Potatoe = 'potatoe',
  Tomatoe = 'tomatoe'
}

// 定义基础公共字段Schema
const BaseSchema = z.object({
  action: z.nativeEnum(Action),
  objectType: z.nativeEnum(ObjectType)
});

// 按`action-objectType`组合映射对应的payload Schema
const payloadSchemas = {
  'create-potatoe': z.object({ weight: z.number() }),
  'create-tomatoe': z.object({ ripeness: z.string() })
} as const;

// 派生虚拟鉴别字段并创建discriminatedUnion
export const TestSchema = BaseSchema
  .transform(data => ({
    ...data,
    type: `${data.action}-${data.objectType}` as const
  }))
  .pipe(
    z.discriminatedUnion('type', 
      Object.entries(payloadSchemas).map(([type, payloadSchema]) => 
        z.object({ type: z.literal(type), payload: payloadSchema }).merge(BaseSchema)
      )
    )
  );

该方案通过将action和objectType组合成虚拟的type字段,实现了discriminatedUnion的使用,适合组合数量多、需要统一维护的场景。

内容的提问来源于stack exchange,提问作者coler-j

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 13:22:43