如何导出挂载在使用React.forwardRef的组件上的子组件?
解决React forwardRef组件挂载子组件的TypeScript类型错误
问题场景
构建UI系统时,需要将一个组件作为静态属性挂载到使用forwardRef的组件上。不使用forwardRef时该操作正常,但添加forwardRef后出现TypeScript类型错误,提示静态属性不存在于ForwardRefExoticComponent类型上。
错误信息
Property 'Secondary' does not exist on type 'ForwardRefExoticComponent<ForwardedRefProps & RefAttributes<HTMLButtonElement>>'
示例代码
interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {} export const ForwardRefButton = React.forwardRef<HTMLButtonElement, ButtonProps>( function Button(props, ref) { return( <button ref={ref}>Ref is forwarded</button> ) } ) ForwardRefButton.Secondary = function () { // 此处出现类型错误 return ( <button>Secondary Button</button> ) }
解决方案
方法一:显式扩展组件类型
通过定义包含静态属性的组件类型,将forwardRef返回的组件断言为该类型,让TypeScript识别静态成员:
import React from 'react'; interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {} // 定义包含Secondary静态属性的组件类型 type ForwardRefButtonComponent = React.ForwardRefExoticComponent< ButtonProps & React.RefAttributes<HTMLButtonElement> > & { Secondary: React.FC; }; // 断言组件类型 export const ForwardRefButton = React.forwardRef<HTMLButtonElement, ButtonProps>( (props, ref) => { return <button ref={ref} {...props}>Ref is forwarded</button>; } ) as ForwardRefButtonComponent; // 挂载静态组件 ForwardRefButton.Secondary = () => <button>Secondary Button</button>;
方法二:封装组件对象
先创建内部的forwardRef组件,再将其赋值给一个包含静态属性的对象,并扩展类型:
import React from 'react'; interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {} // 内部forwardRef组件 const BaseButton = React.forwardRef<HTMLButtonElement, ButtonProps>( (props, ref) => { return <button ref={ref} {...props}>Ref is forwarded</button>; } ); // 扩展类型并添加静态属性 export const ForwardRefButton = BaseButton as typeof BaseButton & { Secondary: React.FC; }; ForwardRefButton.Secondary = () => <button>Secondary Button</button>;
原因说明
React.forwardRef返回的默认类型ForwardRefExoticComponent并未包含自定义静态属性的定义,因此TypeScript会阻止添加未声明的属性。通过扩展类型并断言,我们可以告诉TypeScript该组件包含额外的静态成员,从而解决类型错误。这种做法完全允许在forwardRef组件上挂载静态函数或组件,只是需要明确的类型声明支持。
内容的提问来源于stack exchange,提问作者wongx
相关产品推荐
相关产品推荐

