如何在TypeScript中正确使用Formik的useField?自定义组件传参报错修复
解决Formik自定义输入组件的TypeScript类型错误
问题背景
给自定义组件<MyTextInput/>传递type、placeholder、className等props时触发TypeScript类型错误,不想通过逐个指定props的方式修复,需要通用解决方案。
调用代码
<MyTextInput label="Password:" name="password" placeholder="Enter your password" className="text-pink-600" />
自定义组件代码
import { FieldHookConfig, useField } from 'formik'; import React from 'react'; interface IFieldProps { label?: string; } const MyTextInput: React.FC<IFieldProps & FieldHookConfig<string>> = ({ label, ...props }) => { const { name } = props; const [field, meta] = useField(props); return ( <div className="flex flex-col"> <label htmlFor={name}>{label}</label> <input id={name} type="text" {...field} {...props} /> {/* 此处报错 */} </div> ); }; export default MyTextInput;
报错信息(中文翻译)
类型 '{ ref?: LegacyRef<HTMLInputElement> | undefined; key?: Key | null | undefined; accept?: string | undefined; alt?: string | undefined; autoComplete?: HTMLInputAutoCompleteAttribute | undefined; ... 295 more ...; innerRef?: ((instance: any) => void) | undefined; } | { ...; } | { ...; }' 不能赋值给类型 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'。 类型 '{ ref?: LegacyRef<HTMLSelectElement> | undefined; key?: Key | null | undefined; autoComplete?: string | undefined; disabled?: boolean | undefined; ... 275 more ...; checked?: boolean | undefined; }' 不能赋值给类型 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'。 类型 '{ ref?: LegacyRef<HTMLSelectElement> | undefined; key?: Key | null | undefined; autoComplete?: string | undefined; disabled?: boolean | undefined; ... 275 more ...; checked?: boolean | undefined; }' 不能赋值给类型 'ClassAttributes<HTMLInputElement>'。 属性'ref'的类型不兼容。 类型 'LegacyRef<HTMLSelectElement> | undefined' 不能赋值给类型 'LegacyRef<HTMLInputElement> | undefined'。 类型 '(instance: HTMLSelectElement | null) => void' 不能赋值给类型 'LegacyRef<HTMLInputElement> | undefined'。 类型 '(instance: HTMLSelectElement | null) => void' 不能赋值给类型 '(instance: HTMLInputElement | null) => void'。 参数'instance'和'instance'的类型不兼容。 类型 'HTMLInputElement | null' 不能赋值给类型 'HTMLSelectElement | null'。 类型 'HTMLInputElement' 缺少类型 'HTMLSelectElement' 中的以下属性: length, options, selectedIndex, selectedOptions 及另外4个属性。ts(2322) (property) JSX.IntrinsicElements.input: React.DetailedHTMLProps<React.InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>
修复方案
核心问题是FieldHookConfig默认泛型范围覆盖所有表单元素(如select、checkbox等),导致TypeScript判定props可能属于其他表单元素,与<input>属性不兼容。只需明确限定FieldHookConfig的元素类型为HTMLInputElement:
import { FieldHookConfig, useField } from 'formik'; import React from 'react'; interface IFieldProps { label?: string; } // 明确指定FieldHookConfig的第二个泛型参数为HTMLInputElement const MyTextInput: React.FC<IFieldProps & FieldHookConfig<string, HTMLInputElement>> = ({ label, ...props }) => { const { name } = props; const [field, meta] = useField(props); return ( <div className="flex flex-col"> <label htmlFor={name}>{label}</label> <input id={name} type="text" {...field} {...props} /> {/* 错误修复 */} </div> ); }; export default MyTextInput;
原理说明
FieldHookConfig的第二个泛型参数用于指定表单元素类型,默认值是HTMLElement,会涵盖所有表单相关元素。指定为HTMLInputElement后,TypeScript会将props类型限定为<input>元素的属性,既解决了ref等属性的类型冲突,又保留了自动传递所有input相关props的能力,无需逐个手动指定。
内容的提问来源于stack exchange,提问作者ThanK
相关产品推荐
相关产品推荐

