使用[key:string]: any规避泛型额外函数?React recompose类型问询
Let me break down a cleaner, type-safe solution that avoids both the extra wrapper function and the unsafe any index signature you're dealing with.
First, let's recap the core issue: when using compose from recompose, you want your enhanced component to accept both the props defined in your base IOuterProps and any additional props your component needs, while still maintaining type safety for all of them.
The Optimal Solution: Generic Cross-Types
Instead of wrapping compose in an extra function or resorting to any, we can define a generic type for our enhancer that explicitly models the prop passthrough behavior of higher-order components. Here's how:
import { compose } from 'recompose'; import React from 'react'; // Your base prop interfaces interface IOuterProps { somethingYouGiveMe: string; } interface IInnerProps { somethingIGiveBack: number; } // Define a generic enhancer type that supports extra props type MyEnhancer = <ExtraProps extends {}>( component: React.ComponentType<IInnerProps & ExtraProps> ) => React.ComponentType<IOuterProps & ExtraProps>; // Assign compose result to our enhancer type (cast is safe here) const myEnhancer: MyEnhancer = compose( myHoC, myOtherHoc ) as MyEnhancer;
Now when you use this enhancer with your component that has extra props:
interface IMyComponentProps { somethingYouGiveMe: string; somethingElse: string; // Extra prop } const MyComponent = ({ somethingIGiveBack, somethingElse }: IInnerProps & { somethingElse: string }) => ( <div>{somethingIGiveBack} - {somethingElse}</div> ); const MyEnhancedComponent = myEnhancer(MyComponent); // This works perfectly - TypeScript recognizes all required props <MyEnhancedComponent somethingYouGiveMe="test" somethingElse="extra" />;
Why This Works
- Type Safety: We use TypeScript's intersection types (
&) to combine your base props with any extra props your component needs. Noanymeans all props are checked by the compiler. - No Extra Wrappers: We avoid creating an unnecessary wrapper function by directly typing the result of
composewith our genericMyEnhancertype. The type cast is safe here because we're accurately modeling howcomposeand your HoCs behave. - Clear Intent: The generic type explicitly communicates that your enhancer accepts components with additional props and returns a component that accepts those same extra props alongside your base
IOuterProps.
Comparing to Your Original Solutions
- Against Solution 1: You don't need to create a wrapper function just to add generics. This approach keeps your code cleaner while achieving the same type flexibility.
- Against Solution 2: Ditching
[key: string]: anymeans you lose none of TypeScript's type checking benefits. You'll get errors if you pass invalid props or forget required ones, which is exactly what we want.
Bonus: If Your HoCs Have Precise Types
If your individual HoCs are already typed correctly to handle extra props, you might even be able to avoid the type cast entirely by letting TypeScript infer the generic enhancer type. But in cases where recompose's built-in types are too restrictive, the explicit type definition above is a reliable workaround.
内容的提问来源于stack exchange,提问作者Matt Greer

