You need to enable JavaScript to run this app. TypeScript下结合React.lazy、Suspense与forwardRef编写异步HOC的类型报错处理
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript下结合React.lazy、Suspense与forwardRef编写异步HOC的类型报错处理

类型报错根因与修复方案

核心错误来源

原代码的类型报错完全来自两处对React API泛型规则的错位使用:

  • 记错了forwardRef的泛型参数顺序:这个API的泛型签名是forwardRef<RefInstanceType, PropsType>,第一个参数对应ref指向的组件实例类型,第二个参数才是组件接收的props类型。原代码把props类型P直接传给了第一个泛型位,导致ref类型和props类型完全错位,触发全链路类型不匹配报错。
  • 泛型缺少基础约束:props相关的泛型没有加extends object的限制,和React内部组件的props类型校验规则不兼容,进一步放大了类型推导的错误。

具体修复调整

  • 给所有props相关的泛型加上extends object约束,完全匹配React组件的props类型要求
  • 修正forwardRef的泛型传参顺序,把props类型放到第二个泛型位,第一个泛型位默认用unknown承接ref类型,需要强类型时TS会自动从加载的组件类型里推导
  • 去掉硬编码的ComponentType<P>返回值标注,让TS根据forwardRef的返回值自动生成正确的、带ref转发能力的组件类型,避免返回值类型不匹配

修复后可直接运行的代码

import { ComponentType, forwardRef, Ref, lazy, Suspense } from 'react';

type AsyncComponentFactory<P extends object> = () => Promise<{ default: ComponentType<P> }>;

export function loadable<P extends object, RefType = unknown>(factory: AsyncComponentFactory<P>) {
  const LazyComponent = lazy(factory);

  const WrappedWithLoadableComponent = forwardRef<RefType, P>((props, ref) => (
    <Suspense fallback="loading">
      <LazyComponent {...props} ref={ref} />
    </Suspense>
  ));

  WrappedWithLoadableComponent.displayName = 'LazyExoticComponent(loadableComponent)';

  return WrappedWithLoadableComponent;
}

const JobsView = loadable(() => import(/* webpackChunkName: "JobsView" */ '@views/Jobs'));

修复后的实际表现

  • 传入组件的props会完整透传给异步加载的目标组件,类型完全匹配,不会触发类型校验报错
  • 外层包裹的组件可以正常通过ref获取到内部异步组件的实例,ref的类型会根据内部组件的定义自动推导,不需要额外写类型断言

内容的提问来源于stack exchange,提问作者SWAN ZHANG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.11 12:15:04