React.forwardRef包裹泛型组件后丢失泛型类型推断如何解决?
问题根因
React.forwardRef 的内置 TypeScript 类型定义默认会抹除被包裹函数的泛型参数,无法将泛型参数透传到最终返回的组件上,因此会出现类型推断失效问题。
修复方案
最常用的解决方式是手动为被 React.forwardRef 包裹后的组件声明泛型类型,通过类型断言保留泛型能力:
修复后完整代码示例
import React, { forwardRef } from 'react'; interface IUser { nickname: string; } interface IList<TRecord> { items: TRecord[]; children: (item: TRecord) => React.ReactElement; } // 1. 先定义带泛型的 List 组件类型,包含ref参数 type ListComponentType = <TRecord>( props: IList<TRecord> & { ref?: React.Ref<HTMLUListElement> } ) => React.ReactElement | null; // 2. 用forwardRef包裹后,手动断言为上面定义的泛型类型 export const List = forwardRef<HTMLUListElement, IList<any>>((props, ref) => { return ( <ul ref={ref}> {props.items.map(x => <li>{props.children(x)}</li>)} </ul> ); }) as ListComponentType; // 使用时类型推断完全正常 export const MyApp = () => { const items : IUser[] = []; return ( <List items={items}> {/* item会被自动推断为IUser类型,可正常提示nickname属性 */} {item => <p>{item.nickname}</p>} </List> ); }
通用工具封装(可选)
如果项目中需要频繁创建带泛型的forwardRef组件,可以封装一个通用工具函数,避免每次重复写类型断言:
import React, { forwardRef, ForwardRefRenderFunction } from 'react'; export const createGenericForwardRef = <Props, RefType = unknown>() => { return (render: ForwardRefRenderFunction<RefType, Props>) => { return forwardRef(render) as <T extends Props>( props: T & { ref?: React.Ref<RefType> } ) => React.ReactElement | null; }; }; // 使用示例 const forwardRef = createGenericForwardRef<IList<any>, HTMLUListElement>(); export const List = forwardRef((props, ref) => { return ( <ul ref={ref}> {props.items.map(x => <li>{props.children(x)}</li>)} </ul> ); });
注意事项
- 示例中ref的类型指定为
HTMLUListElement,可根据实际需求替换为对应的DOM类型或者自定义组件实例类型,不要使用any避免丢失ref的类型提示 - 类型断言仅适用于组件逻辑和声明的类型完全匹配的场景,不会引入额外的类型安全问题
内容的提问来源于stack exchange,提问作者Jolly
相关产品推荐
相关产品推荐

