如何为TypeScript联合类型User构建Yup验证Schema?
解决Yup联合类型Schema的TypeScript类型匹配问题
问题原因
你当前的Schema定义中,privileges字段被声明为可选字符串,但你的User联合类型要求:
- 当
authenticationType为basicUser时,privileges是必填字符串 - 当
authenticationType为adminUser时,privileges字段不存在
这种结构差异导致TypeScript无法将你的ObjectSchema与User类型对齐,即使运行时验证正常,类型检查也会失败。
可行解决方案:使用yup.lazy动态匹配分支Schema
通过yup.lazy根据authenticationType的值动态选择对应的子Schema,完美匹配联合类型的结构:
步骤1:定义各分支的独立Schema
先分别为BasicUser和AdminUser创建精确匹配的Schema:
import * as yup from 'yup'; import { AuthenticationType, User, BasicUser, AdminUser } from './types'; // 定义BasicUser的Schema const basicUserSchema = yup.object<BasicUser>().shape({ name: yup.string().required(), authenticationType: yup.string().oneOf(['basicUser']).defined().required(), privileges: yup.string().required() }); // 定义AdminUser的Schema const adminUserSchema = yup.object<AdminUser>().shape({ name: yup.string().required(), authenticationType: yup.string().oneOf(['adminUser']).defined().required() });
步骤2:用yup.lazy组合成联合Schema
使用lazy根据输入值的authenticationType动态选择对应的Schema,同时指定类型为yup.Schema<User>:
const userSchema: yup.Schema<User> = yup.lazy((value) => { switch (value?.authenticationType) { case 'basicUser': return basicUserSchema; case 'adminUser': return adminUserSchema; default: // 默认返回一个会验证失败的Schema,处理未知类型 return yup.object().test('invalid-type', 'Invalid user type', () => false); } });
验证测试
现在可以正常验证你的示例数据,同时TypeScript类型检查完全通过:
// 验证AdminUser userSchema.validate(bobAdmin) .then(validUser => console.log(validUser)) // 正常通过 .catch(err => console.error(err)); // 验证BasicUser userSchema.validate(sallyBasicUser) .then(validUser => console.log(validUser)) // 正常通过 .catch(err => console.error(err)); // 验证缺少privileges的BasicUser会报错 userSchema.validate({ name: 'Test', authenticationType: 'basicUser' }) .catch(err => console.error(err)); // 提示privileges必填
另一种方案:使用yup.mixed().oneOf()结合Schema数组
如果你偏好oneOf的写法,也可以将两个分支Schema放入oneOf中:
const userSchema: yup.Schema<User> = yup.mixed().oneOf([ basicUserSchema, adminUserSchema ]) as yup.Schema<User>;
注意:这里的类型断言
as yup.Schema<User>是必要的,因为Yup的类型推断无法自动识别数组中的Schema对应联合类型。
关键技巧总结
- 联合类型的Schema需要精确匹配每个分支的结构,不能用单一ObjectSchema覆盖所有情况
yup.lazy是处理动态类型最可靠的方式,能根据输入值动态切换验证逻辑- 避免在单一ObjectSchema中用
when处理联合类型的必填差异,这种方式无法让TypeScript正确推断类型
内容的提问来源于stack exchange,提问作者cgatian
相关产品推荐
相关产品推荐

