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

基于TS联合类型TPlan构建Yup验证Schema并实现类型推断

问题:基于TypeScript联合类型构建正确的Yup验证Schema

已有如下TypeScript联合类型TPlan:

type TPlan =
  | {
      type: "pro";
      content: { signedAt: string; expiresOn: string };
    }
  | {
      type: "default" | "regular";
      content: { signedAt: string };
    };

针对两种结构分别定义了Yup验证Schema:

import * as yup from 'yup';

const schemaA = yup.object({
  type: yup.mixed<"pro">().oneOf(["pro"]).defined(),
  content: yup.object({
    signedAt: yup.string().defined(),
    expiresOn: yup.string().defined(),
  }),
});

const schemaB = yup.object({
  type: yup.mixed<"default" | "regular">().oneOf(["default", "regular"]).defined(),
  content: yup.object({
    signedAt: yup.string().defined(),
  }),
});

单独对两个Schema做类型推断时结果正确,但尝试用.oneOf()合并为统一Schema时出现TypeScript类型错误:

// 错误用法,会导致类型不匹配
export const validationSchema = yup.mixed<TSchemaA | TSchemaB>()
  .oneOf([schemaA, schemaB])
  .defined();

需要构建符合TPlan类型的正确Yup验证Schema,同时保证类型推断结果准确。


解决方案

错误原因

.oneOf()方法的作用是验证输入值属于指定的枚举值集合,而非用于合并多个验证Schema,直接传入Schema数组会导致类型不匹配。

方案一:使用yup.union(推荐)

Yup提供了union方法专门用于合并多个Schema,它会依次尝试用每个子Schema验证输入值,只要符合其中一个即可通过验证。

import * as yup from 'yup';

// 定义TPlan及子Schema(同上文)...

// 使用union合并两个Schema
export const validationSchema = yup.union([schemaA, schemaB]).defined();

// 类型推断结果与TPlan完全一致
type InferedTPlan = yup.InferType<typeof validationSchema>;
// InferedTPlan 等价于 TPlan

方案二:自定义test验证逻辑

如果需要更灵活的验证控制,可以通过mixed().test()自定义测试函数,手动验证输入是否符合任一子Schema:

export const validationSchema = yup.mixed<TPlan>()
  .test({
    name: 'plan-structure-validation',
    test: async (value) => {
      // 尝试用schemaA验证
      try {
        await schemaA.validate(value, { abortEarly: false });
        return true;
      } catch {}

      // 尝试用schemaB验证
      try {
        await schemaB.validate(value, { abortEarly: false });
        return true;
      } catch {}

      return false;
    },
    message: '输入的计划结构不符合要求',
  })
  .defined();

类型推断说明

  • 使用union方法时,InferType会自动将结果推断为两个子Schema的联合类型,完全匹配原始的TPlan。
  • 使用自定义test方式时,需要手动指定泛型为TPlan,确保类型推断结果准确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 18:10:37