我在 React 中使用 recompose,特别是它的compose
函数,它的签名为
function compose<TInner, TOutter>(
...functions: Function[]
): ComponentEnhancer<TInner, TOutter>;
interface ComponentEnhancer<TInner, TOutter> {
(component: Component<TInner>): ComponentClass<TOutter>;
}
我在其中传递了一些 React 高阶组件。我将我的TInner
和TOuter
类型定义为接口,这些接口描述了我的 HoC 运行所需的内容:
interface IOuterProps {
somethingYouGiveMe: string;
}
interface IInnerProps {
somethingIGiveBack: number;
}
const myEnhancer = compose<IInnerProps, IOuterProps>(myHoC, myOtherHoc);
(作为演示的愚蠢示例)。但问题是,我的组件有更多的 props,compose 生成的 HoC 需要获取这些额外的 props 并传递它们,例如:
interface IMyComponentProps {
somethingYouGiveMe: string;
somethingElse: string;
}
因此,我不能这样做const MyEnhancedComponent = myEnhancer(MyComponent)
,因为编译器会抱怨MyEnhancedComponent
没有somethingElse
作为道具。
我找到了两个解决方法,我都不满意。很好奇更有经验的 TypeScript 开发人员会做什么。
解决方法#1:引入一个函数
通过引入一个函数,我可以使用泛型并向编译器表达我在做什么
function myEnhancer<TInnerProps extends IInnerProps, TOuterProps extends IOuterProps>(Component: React.ComponentType<TInnerProps>) {
return compose<TInnerProps, TOuterProps>(mYHoC, myOtherHoc)(Component);
}
我真的不喜欢这个,引入一个将创建增强器的多个副本的函数,只是为了获得泛型?对我来说似乎是错误的。
解决方法 #2:使用 [key:string]: any
我可以改为将我的界面更改为
interface IOutterProps {
somethingYouGiveMe: string;
[key: string]: any;
}
interface IInnerProps extends IOuterProps {
somethingIGiveBack: number;
}
我基本上[key:string]: any
用作穷人的extends IOutterProps
。比如,我需要你给我这些道具,如果你给我额外的东西,那么我真的不在乎那些。
这使我可以myEnhancer
在我拥有满足要求的组件的任何地方使用,避免添加的功能,并且感觉比解决方法 #1 更好。但是不得不添加也感觉不对[key: string]: any
。