如何使用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类型,仅需两步:
- 扩展产品类型枚举:
type ProductType = 'simple' | 'variables' | 'bundle'; - 定义特有字段并生成子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
相关产品推荐
相关产品推荐

