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

TS/React嵌套使用forwardRef传递ref报TS2322错误如何修复

forwardRef嵌套传递ref时TypeScript类型报错修复

问题复现

在嵌套使用forwardRef封装的React组件时,内层组件接收外层透传的ref时抛出TS类型错误,复现代码如下:

const DEFAULT_ELEMENT = "button";

export type PropsOf<TTag = any> = TTag extends React.ElementType
  ? React.ComponentProps<TTag>
  : never;

export type ButtonProps = PropsOf<typeof DEFAULT_ELEMENT> & {};

// 自定义Button组件,可独立正常运行:
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
  (props, ref) => (<button ref={ref} {...props}/>)
)

// 基于Button封装的IconButton组件,TypeScript对ref属性抛出类型错误:
export const IconButton = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => (
  <Button
    ref={ref} // 此处TS抛出错误
    {...props}
  />
))

抛出的错误信息:

TS2322: Type 'string | ((instance: HTMLButtonElement | null) => void) | RefObject | null' is not assignable to type 'Ref | undefined'.
Type 'string' is not assignable to type 'Ref | undefined'.

报错截图:
ts error

错误原因

  • 你定义的ButtonProps是直接提取原生button标签的属性类型,原生DOM元素的ref类型兼容旧版string类型ref,而forwardRef包装后的组件接收的ref类型Ref<HTMLButtonElement>不支持string类型ref,两者类型范围不匹配。
  • 手动声明的ButtonProps没有关联Button组件的实际ref类型,TS无法识别Button作为forwardRef组件的正确ref签名,透传时直接沿用了原生button的ref类型定义,导致校验失败。

修复方案

推荐使用类型工具自动提取组件的正确props类型(含ref),从根源解决类型不匹配问题:

const DEFAULT_ELEMENT = "button";

export type PropsOf<TTag = any> = TTag extends React.ElementType
  ? React.ComponentProps<TTag>
  : never;

// 先定义基础Button组件
export const Button = forwardRef<HTMLButtonElement, PropsOf<typeof DEFAULT_ELEMENT>>(
  (props, ref) => (<button ref={ref} {...props}/>)
)

// 使用ComponentPropsWithRef提取Button组件的完整合法props类型,自动推导正确的ref类型
export type ButtonProps = React.ComponentPropsWithRef<typeof Button>;

// IconButton使用提取后的ButtonProps,ref传递不再报类型错误
export const IconButton = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => (
  <Button
    ref={ref}
    {...props}
  />
))

如果只是临时修复,也可以在传递ref时做类型断言,但这种方式会丢失部分类型校验能力,不推荐长期使用:

export const IconButton = forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => (
  <Button
    ref={ref as React.Ref<HTMLButtonElement>}
    {...props}
  />
))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 04:51:37