I'm trying to type an Higher Order Component (HOC) using Recompose and its HOC type, using Flow.
This is my code:
// @flow
import React from 'react';
import { compose, defaultProps, withProps, type HOC } from 'recompose';
type InnerProps = {
text: string,
num: number,
};
type EnhancedComponentProps = {
text: string,
};
const baseComponent = ({ text, num }: InnerProps) => (
<div>
{text}
{num}
</div>
);
const enhance: HOC<*, EnhancedComponentProps> = compose(
defaultProps({
text: 'world',
}),
withProps(({ text }) => ({
text: `Hello ${text}`,
}))
);
export default enhance(baseComponent);
Right now this fails with:
Cannot call enhance with baseComponent bound to a because property num is missing in object type [1] but exists in
InnerProps [2] in the first argument.
src/Text.js
[2] 14│ const baseComponent = ({ text, num }: InnerProps) => (
:
27│ }))
28│ );
29│
30│ export default enhance(baseComponent);
31│
flow-typed/npm/recompose_v0.x.x.js
[1] 95│ ): HOC<{ ...$Exact<Enhanced>, ...BaseAdd }, Enhanced>;
Trying to read the docs and some blog posts I couldn't reach to a solution. All the examples I find are very trivial and none of them cover this simple case.
What's the right way to type this code?
I guess you get the right error. It says:
num is missing in object type [1] but exists in InnerProps [2] in the first argument.
You declared that your HOC will get what's in EnhancedComponentProps
which is missing the num
. In other words, you try to extract num
from Object that will only get what's declared in EnhancedComponentProps
type.
Based on recompose docs: you should get this work by:
// @flow
import React from 'react';
import { compose, defaultProps, withProps, type HOC } from 'recompose';
type EnhancedComponentProps = {
text: string,
num: number,
};
const baseComponent = ({ text, num }: EnhancedComponentProps) => ( // in the example from recompose this typing is unnecessary though
<div>
{text}
{num}
</div>
);
const enhance: HOC<*, EnhancedComponentProps> = compose(
defaultProps({
text: 'world',
}),
withProps(({ text }) => ({
text: `Hello ${text}`,
}))
);
export default enhance(baseComponent);