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ê
相关产品推荐
相关产品推荐

