Reputation: 474
I am new to TypeScript and I am struggling to write HOC with typecheck. Here's my HOC:
import React from 'react';
import Firebase from './Firebase';
export type FirebaseType = Firebase;
interface OwnProps {
firebase: typeof Firebase;
}
const FirebaseContext = React.createContext(new Firebase());
export const withFirebase: React.FC = <T extends OwnProps>(
Component: React.ComponentType<T>,
): React.ComponentType<T> => (props) => (
<FirebaseContext.Consumer>
{(firebase: FirebaseType) => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
export default FirebaseContext;
It throws an error:
Type '(Component: React.ComponentType) => React.ComponentType' is not assignable to type 'FC<{}>'. Types of parameters 'Component' and 'props' are incompatible. Type '{ children?: ReactNode; }' is not assignable to type 'ComponentType'. Type '{ children?: ReactNode; }' is not assignable to type 'FunctionComponent'. Type '{ children?: ReactNode; }' provides no match for the signature '(props: PropsWithChildren, context?: any): ReactElement ReactElement Component)> | null) | (new (props: any) => Component<...>)> | null'.ts(2322)
I have absolutely no idea how to move on with this code or how to make it work.
Any thoughts?
Upvotes: 0
Views: 2644
Reputation: 6529
Here's what that error means:
In your type definition, you're expecting withFirebase
to have the same type signature as a function component (React.FC
), which takes in props
and returns a React element (or null).
However, that's not what you want from a HOC, you want it to take in a Component (React.ComponentType
) and return a Component (React.ComponentType
).
This should work:
type HOC = (Component: React.ComponentType) => React.ComponentType;
// Or, if you want to be more specific:
// type HOC = <T extends OwnProps>(Component: React.ComponentType<T>) => React.ComponentType<T>
export const withFirebase: HOC = <T extends OwnProps>(
Component: React.ComponentType<T>,
): React.ComponentType<T> => (props) => (
<FirebaseContext.Consumer>
{(firebase: FirebaseType) => <Component {...props} firebase={firebase} />}
</FirebaseContext.Consumer>
);
Or you can also just omit the HOC type, and TypeScript will infer the correct type from the function definition.
Upvotes: 4