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

使用Formik+Yup时TypeScript无法识别特定输入字段错误类型

解决Formik+Yup+TypeScript数组嵌套错误的类型问题

问题根源

Formik默认的Errors类型无法自动推断数组嵌套结构的错误类型,即便Yup Schema定义了数组规则,TypeScript也没法自动对齐errors对象的深层结构类型——控制台能打印错误结构是因为运行时存在该属性,但编译时TS无法确认其类型,导致访问errors.luxmeds[index].xxx时抛出类型错误。

解决方案

1. 显式定义表单值与错误的TS类型

先明确表单数据结构,或通过Yup的InferType从Schema自动推断类型:

import { InferType } from 'yup';
import * as yup from 'yup';

// 用Yup定义校验规则
const formSchema = yup.object({
  luxmeds: yup.array().of(
    yup.object({
      clinicId: yup.string().required('诊所ID为必填项'),
      visitTypeId: yup.string().required('就诊类型ID为必填项')
    })
  )
});

// 从Schema推断表单值类型
type FormValues = InferType<typeof formSchema>;

// 定义对应错误类型,匹配数组元素的字段结构
type FormErrors = {
  luxmeds?: Array<{
    clinicId?: string;
    visitTypeId?: string;
  }>;
};

2. 在Formik组件中指定泛型类型

将定义好的FormValues和FormErrors传入Formik的泛型参数,让TS明确错误对象的结构:

import { Formik, Form, Field } from 'formik';

<Formik<FormValues, FormErrors>
  initialValues={{ luxmeds: [] }}
  validationSchema={formSchema}
  onSubmit={(values) => console.log(values)}
>
  {({ errors, touched }) => (
    <Form>
      {values.luxmeds.map((_, index) => (
        <div key={index} className="luxmed-item">
          <Field 
            name={`luxmeds[${index}].clinicId`} 
            placeholder="诊所ID"
          />
          {/* 用可选链处理可能的undefined,避免类型报错 */}
          {errors.luxmeds?.[index]?.clinicId && touched.luxmeds?.[index]?.clinicId && (
            <span className="error-text">{errors.luxmeds[index].clinicId}</span>
          )}

          <Field 
            name={`luxmeds[${index}].visitTypeId`} 
            placeholder="就诊类型ID"
          />
          {errors.luxmeds?.[index]?.visitTypeId && touched.luxmeds?.[index]?.visitTypeId && (
            <span className="error-text">{errors.luxmeds[index].visitTypeId}</span>
          )}
        </div>
      ))}
    </Form>
  )}
</Formik>

3. 用Formik的getIn工具函数安全访问(替代方案)

如果不想手动定义错误类型,可使用Formik内置的getIn函数安全获取嵌套错误,自动规避类型问题:

import { getIn } from 'formik';

// 在渲染回调中:
{values.luxmeds.map((_, index) => {
  const clinicIdError = getIn(errors, `luxmeds[${index}].clinicId`);
  const clinicIdTouched = getIn(touched, `luxmeds[${index}].clinicId`);

  return (
    <div key={index}>
      <Field name={`luxmeds[${index}].clinicId`} />
      {clinicIdError && clinicIdTouched && (
        <span className="error-text">{clinicIdError}</span>
      )}
    </div>
  );
})}

本地项目报错但Codesandbox正常的原因

  • 本地TypeScript配置更严格(比如开启了strict: true或strictNullChecks: true),对undefined的检查更严谨;
  • 本地Formik/TS/Yup版本与Codesandbox不一致,导致类型推断逻辑有差异。

内容的提问来源于stack exchange,提问作者marcinb1986

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 08:35:30