使用Yup进行TypeScript Schema校验时可选字段的类型错误
解决Yup与TypeScript中可选字段的Schema类型不兼容问题
我在使用Yup库做TypeScript Schema校验时碰到类型错误。我定义了一个包含部分可选字段的formValidation接口,想把它同时用在loginValidation和signUpValidation两个校验Schema里,但TypeScript提示类型不兼容。
示例代码
import { object, ObjectSchema, string, ref } from 'yup' interface formValidation { email: string, password: string, confirmPassword?: string sex?: 'Male' | 'Female' } const loginValidation: ObjectSchema<formValidation> = object({ email: string().email('Invalid email address').required('Email is required'), password: string().required('Password is required'), }); const signUpValidation: ObjectSchema<formValidation> = object({ email: string().email('Invalid email address').required('Email is required'), password: string().required('Password is required'), confirmPassword: string().oneOf([ref('password')], 'Password must match'), sex: string<'Male' | 'Female'>().required('Sex is required') })
错误信息
Type 'ObjectSchema<{ email: string; password: string; }, AnyObject, { email: undefined; password: undefined; }, "">' is not assignable to type 'ObjectSchema<formValidation, AnyObject, any, "">'. The types of 'default(...).fields' are incompatible between these types. Type 'Shape<{ email: string; password: string; }, AnyObject>' is missing the following properties from type 'Shape<formValidation, AnyObject>': confirmPassword, sex
解决方法
问题根源在于:loginValidation的Schema仅包含必填的email和password,但指定的ObjectSchema<formValidation>要求Schema必须覆盖接口内所有字段(包括可选字段),TypeScript会判定Schema缺少这些字段定义,从而抛出类型不兼容错误。
以下是三种可行的解决方式:
1. 使用Pick类型提取必填字段
将loginValidation的类型改为ObjectSchema<Pick<formValidation, 'email' | 'password'>>,让TypeScript只校验Schema包含这两个必填字段即可:
const loginValidation: ObjectSchema<Pick<formValidation, 'email' | 'password'>> = object({ email: string().email('Invalid email address').required('Email is required'), password: string().required('Password is required'), });
2. 拆分接口为公共+子接口结构
把公共字段抽离成基础接口,再分别定义登录、注册专属接口,结构更清晰:
interface BaseFormValidation { email: string; password: string; } interface LoginFormValidation extends BaseFormValidation {} interface SignUpFormValidation extends BaseFormValidation { confirmPassword: string; sex: 'Male' | 'Female'; } // 对应使用各自的接口 const loginValidation: ObjectSchema<LoginFormValidation> = object({ email: string().email('Invalid email address').required('Email is required'), password: string().required('Password is required'), }); const signUpValidation: ObjectSchema<SignUpFormValidation> = object({ email: string().email('Invalid email address').required('Email is required'), password: string().required('Password is required'), confirmPassword: string().oneOf([ref('password')], 'Password must match').required(), sex: string<'Male' | 'Female'>().required('Sex is required') });
3. 用partial()标记可选字段
如果想保留原formValidation接口,可在loginValidation的Schema上调用partial(),明确告知TypeScript这些可选字段无需在Schema中定义:
const loginValidation: ObjectSchema<formValidation> = object({ email: string().email('Invalid email address').required('Email is required'), password: string().required('Password is required'), }).partial(['confirmPassword', 'sex']);
内容的提问来源于stack exchange,提问作者Lord Konadu Kweku
相关产品推荐
相关产品推荐

