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

Yup根据属性值条件扩展根Object Schema实现方案

问题原因

写法不生效的核心原因是:yup 的 .when() 方法设计用于调整已提前声明的字段的校验规则,不支持在条件回调中通过 .shape() 给当前层级动态追加未提前声明的新字段。
你写的嵌套版本能运行,是因为提前在根层声明了extendedFields这个对象字段,.when()只是修改这个已存在字段的内部结构,符合API设计逻辑;但直接在根schema上调用.when()动态追加根级字段,属于在schema初始化完成后修改根结构,不会被yup识别。

可行实现方案

不需要通过根级when动态合并shape,只需要提前在根层声明所有可能出现的字段,通过when控制字段是否参与校验即可,同时完全保留baseSchema的复用性:

单字段复用写法

如果复用的字段数量少,可以直接引用baseSchema内的字段规则:

// 可独立复用的基础Schema
const baseSchema = yup.object({
  firstName: yup.string().required()
}).required();

const TRUE_FLASE = ["true", "false"];
const extendedSchema = yup.object({
  hasOtherFields: yup.mixed().required().oneOf([...TRUE_FLASE]),
  // 提前声明firstName字段,复用baseSchema内的规则,通过when控制校验逻辑
  firstName: baseSchema.fields.firstName.when("hasOtherFields", {
    is: (val) => val === "true",
    then: (schema) => schema.required(),
    // 当hasOtherFields为false时,剔除firstName字段,不参与校验和结果返回
    otherwise: (schema) => schema.strip()
  })
}).required();

多字段批量复用写法

如果baseSchema包含多个需要条件追加的字段,可以遍历字段批量加规则,不需要重复编写:

const TRUE_FLASE = ["true", "false"];
const baseSchema = yup.object({
  firstName: yup.string().required(),
  // 其他可复用字段
}).required();

// 批量给baseSchema的所有字段加上条件校验逻辑
const conditionalBaseFields = Object.fromEntries(
  Object.entries(baseSchema.fields).map(([fieldKey, fieldSchema]) => [
    fieldKey,
    fieldSchema.when("hasOtherFields", {
      is: (val) => val === "true",
      then: (schema) => schema.required(),
      otherwise: (schema) => schema.strip()
    })
  ])
);

const extendedSchema = yup.object({
  hasOtherFields: yup.mixed().required().oneOf([...TRUE_FLASE]),
  ...conditionalBaseFields
}).required();
类型推导

上述写法可以直接通过yup自带的InferType推导出你期望的联合类型,不需要额外手动定义:

type SchemaType = yup.InferType<typeof extendedSchema>;
// 推导结果等价于:{hasOtherFields: "false"} | {hasOtherFields: "true"; firstName: string}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 20:51:30