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

如何使用Zod高级判别联合?动态控制stock字段必填性

用Zod实现基于判别联合的动态stock字段校验

核心思路

把库存相关的校验逻辑封装成通用工具函数,通过嵌套判别联合(先按type区分产品类型,再按isStockable区分库存规则)实现动态校验,彻底避免新增产品类型时的重复代码。

实现方案

1. 编写通用schema生成函数

这个函数接收产品类型标识和特有字段schema,自动生成包含库存规则的完整子schema:

import { z } from 'zod';

// 产品类型枚举,后续新增类型直接扩展这里
type ProductType = 'simple' | 'variables';

const createProductTypeSchema = <T extends ProductType>(
  type: T,
  specificFields: z.ZodObject<any>
) => {
  // 基础公共字段:产品类型 + 特有字段
  const baseSchema = z.object({
    type: z.literal(type),
    ...specificFields.shape
  });

  // 可库存产品规则:isStockable为true时,stock必填正整数
  const stockableVariant = baseSchema.extend({
    isStockable: z.literal(true),
    stock: z.number().int().positive()
  });

  // 不可库存产品规则:isStockable为false时,stock可选/可空
  const nonStockableVariant = baseSchema.extend({
    isStockable: z.literal(false),
    stock: z.number().int().positive().optional().nullable()
  });

  // 针对isStockable的判别联合,实现动态校验逻辑
  return z.discriminatedUnion('isStockable', [stockableVariant, nonStockableVariant]);
};

2. 定义各产品类型的特有字段

只需针对simple和variables类型编写专属字段规则,无需关心库存逻辑:

// Simple产品特有字段
const simpleSpecific = z.object({
  price: z.number().positive(),
  sku: z.string().nonempty()
});

// Variables产品特有字段
const variablesSpecific = z.object({
  options: z.array(z.string().nonempty()),
  basePrice: z.number().positive()
});

3. 生成完整的产品判别联合schema

将各类型的子schema组合成最终的校验规则:

const productSchema = z.discriminatedUnion('type', [
  createProductTypeSchema('simple', simpleSpecific),
  createProductTypeSchema('variables', variablesSpecific)
]);

扩展新类型的方式

如果新增bundle类型,仅需两步:

  1. 扩展产品类型枚举:type ProductType = 'simple' | 'variables' | 'bundle';
  2. 定义特有字段并生成子schema:
const bundleSpecific = z.object({
  includedProducts: z.array(z.string().nonempty()),
  discountRate: z.number().min(0).max(1)
});

// 更新产品schema
const productSchema = z.discriminatedUnion('type', [
  createProductTypeSchema('simple', simpleSpecific),
  createProductTypeSchema('variables', variablesSpecific),
  createProductTypeSchema('bundle', bundleSpecific)
]);

方案优势

  • 零重复代码:库存校验逻辑集中维护,新增类型无需重复编写
  • 强类型安全:嵌套判别联合让TypeScript能精准推断不同场景下的类型(比如isStockable: true时stock必然存在)
  • 高可维护性:调整库存规则只需修改通用函数,无需逐个修改产品类型schema

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 00:12:56