TypeScript中Yup的InferType将notRequired嵌套字段错误推导为必填项
问题原因
这个问题本质是TypeScript类型规则和Yup类型推导逻辑的共同结果:
- TypeScript中
key: T | undefined和key?: T是两种完全不同的类型:前者要求键必须存在,值可以为undefined;后者才允许完全省略该键。 - 截止当前最新稳定版Yup,调用嵌套对象schema的
.notRequired()/.optional()方法时,类型推导只会给字段值类型加上| undefined,不会自动给对象键添加可选修饰符?,就会出现你遇到的:显式传taxonomy: undefined不报错,但省略字段就报类型错误的现象。2020年官方修复的是基础类型字段的可选推导问题,嵌套对象的可选键修饰符透传问题一直没有完全覆盖。
解决方法
你可以任选以下一种方案修复:
- 方案1:在定义嵌套子schema时,链式调用
.default(undefined),此时Yup的类型推导会自动给对应字段加上可选键修饰符,无需额外处理即可正常省略属性。
修正后的示例代码:import { object, string, InferType } from 'yup'; const taxonomySchema = object({ code: string().required(), }).default(undefined); // 加这一行即可 const platformSchema = object({ name: string().required(), taxonomy: taxonomySchema.notRequired(), }); type Platform = InferType<typeof platformSchema>; const platform: Platform = { name: 'Foo', }; // 此时无类型报错 - 方案2:写一个通用工具类型修正Yup的推导结果,自动把值包含
undefined的字段转为可选键,不需要修改原有schema定义:type FixYupOptional<T> = { [K in keyof T as undefined extends T[K] ? never : K]: T[K]; } & { [K in keyof T as undefined extends T[K] ? K : never]?: T[K]; }; // 使用时包裹InferType的结果即可 type Platform = FixYupOptional<InferType<typeof platformSchema>>; - 方案3:检查项目中Yup的导入方式,不要混用
import * as yup from 'yup'和单独解构导入import { object } from 'yup'两种写法,统一导入方式可以避免部分类型引用不一致导致的推导异常。如果仍有问题,可以在tsconfig中暂时关闭exactOptionalPropertyTypes配置,此时key: T | undefined的类型也允许省略键。
注意:不要为了绕过报错直接给字段加
.nullable(),这会允许字段值为null,和你预期的「可选、不传即为undefined」的校验逻辑不一致。
内容的提问来源于stack exchange,提问作者Jurjan
相关产品推荐
相关产品推荐

