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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:19:52