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

Yup从0.32.11迁移至1.0.2时的TypeScript类型错误问题

问题背景

现有React状态变量:

const [selectedFormtype, setSelectedFormtype] = useState<Nullable<MyFormTypeVm>>()

相关类型定义:

type Nullable<T> = T | null

interface MyFormTypeVm {
    readonly id: NonNullable<string>
    readonly labelCompanyId: Nullable<string>
}

interface MyFormVm {
    companyId: Nullable<string>
    // 其他属性省略
}

在yup@0.32.11版本中,原本可用的验证方案:

const validationSchema: yup.SchemaOf<MyFormVm> = yup.object().shape({
    companyId: yup.string().when([], {
        is: () => selectedFormtype?.labelCompanyId,
        then: yup.string()
            .required('Company-id is required')
            .matches(/^[8|9]\d{8}$/i, 'Company-id has to start with 8 or 9')
    })
).required()

按照yup迁移指南改写验证逻辑后,出现TS2322类型错误,改写后的代码:

const validationSchema: yup.ObjectSchema<MyFormVm> = yup.object().shape({
        companyId: yup.string().when('other', ([], schema) => {
            return selectedFormtype?.labelCompanyId
                ? schema
                      .required('required text goes here')
                      .matches(/^[8|9]\d{8}$/i, 'regex text goes here')
                : schema
        })
})

已在tsconfig.json中配置:

"strictNullChecks": true,
"strictFunctionTypes": false

错误原因分析

  1. when参数错误:验证逻辑依赖外部状态selectedFormtype,而非表单内的other字段,传入'other'会导致TS类型推导混乱。
  2. 类型不兼容:MyFormVm的companyId是Nullable<string>,但触发必填规则后,schema会强制要求非空字符串,和原接口类型冲突。
  3. 缺少nullable声明:原schema未显式标记companyId允许为null,导致TS无法识别动态的可空/必填约束。

解决方法

1. 修正when的触发参数

因为依赖外部状态,when的第一个参数应传空数组[],而非表单字段名:

yup.string().when([], ([], schema) => { ... })

2. 显式处理可空类型

给yup.string()添加.nullable(),让TS识别companyId的可空特性,同时兼容动态必填规则:

const validationSchema: yup.SchemaOf<MyFormVm> = yup.object().shape({
    companyId: yup.string().nullable().when([], ([], schema) => {
        return selectedFormtype?.labelCompanyId
            ? schema
                  .required('required text goes here')
                  .matches(/^[8|9]\d{8}$/i, 'regex text goes here')
            : schema
    })
}).required()

3. 确保验证逻辑响应状态变化

由于selectedFormtype是React状态,需用useMemo依赖该状态生成schema,避免状态更新后验证逻辑不生效:

const validationSchema = useMemo(() => yup.object().shape({
    companyId: yup.string().nullable().when([], ([], schema) => {
        return selectedFormtype?.labelCompanyId
            ? schema
                  .required('required text goes here')
                  .matches(/^[8|9]\d{8}$/i, 'regex text goes here')
            : schema
    })
}).required(), [selectedFormtype])

4. 类型断言兜底(谨慎使用)

如果上述方法仍有类型错误,可通过类型断言强制TS认可schema兼容性:

const validationSchema: yup.ObjectSchema<MyFormVm> = yup.object().shape({
    companyId: (yup.string().when([], ([], schema) => {
        return selectedFormtype?.labelCompanyId
            ? schema
                  .required('required text goes here')
                  .matches(/^[8|9]\d{8}$/i, 'regex text goes here')
            : schema
    }) as yup.Schema<Nullable<string>>)
}).required()

内容的提问来源于stack exchange,提问作者Roar S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 22:07:04