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

TypeScript编写React HOC组合函数如何推导注入props的交叉类型

实现修正方案

你的原有实现核心问题出在PropsType的推导逻辑:你在HOCType的泛型约束中强制第二个参数为never,导致无法正确提取每个HOC注入的属性集合,最终无法自动推导原始组件的props类型。以下是完整修正方案:

1. 修正HOC通用类型与createHOC实现

import React from 'react';

// 定义通用HOC类型:接收需要注入Injected属性的组件,返回不需要传入Injected属性的新组件
type HOC<Injected extends object, Rest extends object = any> = 
  <C extends React.ComponentType<Injected & Rest>>(component: C) => 
    React.ComponentType<Rest>;

// 重写createHOC类型,确保hookFn入参类型安全
function createHOC<Injected extends object>(
  hookFn: <Rest extends object>(restProps: Rest) => Injected,
  displayName: string
): HOC<Injected> {
  return function hoc(Component) {
    const UiHOC = (props: any) => {
      const hookData = hookFn(props);
      return <Component {...props} {...hookData} />;
    };

    const oriDisplayName = Component.displayName || Component.name || '';
    UiHOC.displayName = `${displayName}(${oriDisplayName})`;

    return UiHOC;
  };
}

2. 测试HOC定义(和原有逻辑一致)

const uiHOC1 = createHOC(() => ({ a: '1' }), 'uiHOC1');
const uiHOC2 = createHOC(() => ({ b: 2, c: false }), 'uiHOC2');

3. 修正compose函数类型推导

// 提取单个HOC的注入属性类型
type ExtractInjected<H> = H extends HOC<infer Injected, any> ? Injected : never;
// 联合类型转交叉类型工具
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
// 提取所有HOC注入属性的交叉类型
type AllInjected<Fns extends any[]> = UnionToIntersection<ExtractInjected<Fns[number]>>;

// compose函数实现
function compose<Fns extends HOC<any, any>[]>(
  ...hocs: [...Fns]
): <C extends React.ComponentType<AllInjected<Fns>>>(
  Component: C
) => React.ComponentType<Omit<React.ComponentProps<C>, keyof AllInjected<Fns>>> {
  // 运行时逻辑:从右往左依次执行HOC
  return (Component) => hocs.reduceRight((acc, hoc) => hoc(acc), Component);
}

4. 最终用法(自动推导props类型)

const ComponentWithHOCs = compose(
  uiHOC1,
  uiHOC2
)((props) => {
  // 此处props.a/props.b/props.c均有正确类型推导,无报错
  return <>{props.a} {props.b} {props.c ? '是' : '否'}</>;
});

修正后效果

  • 原始组件不需要手动声明props类型,自动推导为所有HOC注入属性的交叉类型
  • 最终生成的组件会自动排除所有已被注入的属性,外部调用时不需要重复传a/b/c
  • 全链路类型安全,无多余的any声明

内容的提问来源于stack exchange,提问作者Khôi Lê

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 09:06:05