使用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
相关产品推荐
相关产品推荐

