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

Formik封装Antd Input报TS2322类型不兼容错误如何解决

问题现象

编写基于Formik的自定义Antd Input组件时,触发TypeScript TS2322类型报错,原始组件代码如下:

import { Input } from 'antd';
import { useField, FieldHookConfig } from 'formik';

const Text = ({ ...props }: FieldHookConfig<string>) => {
  const [field] = useField(props);
  return <Input {...field} {...props} />;
};
export default FormTextField;

完整报错信息:

TS2322: Type '{ className: string | undefined; ref?: LegacyRef<HTMLInputElement> | undefined; key?: Key | null | undefined; accept?: string | undefined; ... 288 more ...; innerRef?: ((instance: any) => void) | undefined; } | { ...; } | { ...; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Input> & Pick<Readonly<InputProps>, "color" | ... 290 more ... | "bordered"> & InexactPartial<...> & InexactPartial<...>'.
  Type '{ className: string | undefined; ref?: LegacyRef<HTMLInputElement> | undefined; key?: Key | null | undefined; accept?: string | undefined; alt?: string | undefined; ... 287 more ...; innerRef?: ((instance: any) => void) | undefined; }' is not assignable to type 'IntrinsicClassAttributes<Input>'.
    Types of property 'ref' are incompatible.
      Type 'LegacyRef<HTMLInputElement> | undefined' is not assignable to type 'LegacyRef<Input> | undefined'.
        Type '(instance: HTMLInputElement | null) => void' is not assignable to type 'LegacyRef<Input> | undefined'.
          Type '(instance: HTMLInputElement | null) => void' is not assignable to type '(instance: Input | null) => void'.
            Types of parameters 'instance' and 'instance' are incompatible.
              Type 'Input | null' is not assignable to type 'HTMLInputElement | null'.
                Type 'Input' is missing the following properties from type 'HTMLInputElement': accept, align, alt, autocomplete, and 329 more.
报错根因
  • Formik的useField返回的field对象中携带的ref指向原生HTMLInputElement DOM节点
  • Antd的Input是封装后的组件,它本身的ref属性要求指向Antd Input组件实例,而非原生DOM节点,要获取原生输入框DOM需要通过innerRef属性传入
  • 直接全量展开field属性时,类型不匹配的ref被透传给Antd Input,触发TS类型校验失败
  • 代码本身存在额外问题:组件定义名是Text,导出名是FormTextField,命名不一致
修复方案

根据是否需要使用Formik提供的ref,选择对应实现:

方案1:需要保留ref绑定(推荐)

从field中解构出ref,将剩余属性透传给Input,同时把ref绑定到Antd Input提供的innerRef属性上,同时合并Antd Input的Props类型,避免类型缺失:

import { Input } from 'antd';
import { useField, FieldHookConfig } from 'formik';
import type { InputProps } from 'antd/es/input';

// 合并Formik字段配置与Antd Input原生属性类型
type AppFormInputProps = FieldHookConfig<string> & InputProps;

const FormTextField = (props: AppFormInputProps) => {
  const [field] = useField(props);
  // 分离出ref和其他表单绑定属性
  const { ref: formikInputRef, ...restFieldProps } = field;
  return (
    <Input
      {...restFieldProps}
      {...props}
      // Antd Input通过innerRef接收原生DOM的ref
      innerRef={formikInputRef}
    />
  );
};

export default FormTextField;

方案2:不需要使用ref(最简实现)

绝大多数表单场景只需要Formik同步值、校验状态,不需要用到field返回的ref,此时直接将ref解构丢弃即可:

import { Input } from 'antd';
import { useField, FieldHookConfig } from 'formik';
import type { InputProps } from 'antd/es/input';

type AppFormInputProps = FieldHookConfig<string> & InputProps;

const FormTextField = (props: AppFormInputProps) => {
  const [field] = useField(props);
  // 排除不需要的ref属性,避免类型冲突
  const { ref: _, ...restFieldProps } = field;
  return <Input {...restFieldProps} {...props} />;
};

export default FormTextField;

注意:不要直接用@ts-ignore忽略这类报错,否则后续组件属性变更、ref调用时容易出现运行时错误。


内容的提问来源于stack exchange,提问作者A curious student

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 01:48:33