Code example:
// @flow
import * as React from 'react';
type Props = {
foo: number, // foo is required.
bar: 'bar' | 'baz', // bar is not required: it's in the defaultProps
};
class MyComponent extends React.Component<Props> {
static defaultProps = {
bar: 'bar',
};
}
// all's fine
<MyComponent foo={42} />;
// but how to type an object that will be passed to MyComponent via spread?
// 1. Obviously wrong way: flow will not try to understand how we will use myCompProps
// const myCompProps: Props = { foo: 42 }; // - property `bar` missed
// 2. Less obviously wrong way
// const myCompProps: $PropertyType<MyComponent, 'props'> = { foo: 42 }; // - property `bar` missed
<MyComponent {...myCompProps} />;
You can try it
So, we need a convinient way to create a type based on Props and defaultProps. It should be exactly like Props, but all props from defaultProps should be marked as optional.
I'm guessing this is the same issue, or at least similar:
// @flow
import * as React from 'react';
type Props = {
foo: number, // foo is required.
bar: 'bar' | 'baz', // bar is not required: it's in the defaultProps
};
class MyComponent extends React.Component<Props> {
static defaultProps = {
bar: 'bar',
};
}
// all's fine
<MyComponent foo={42} />;
function getComponent(compProps: Props) {
return <MyComponent {...compProps} />
}
getComponent({foo: 2})
try flow link: try it
What about this? Basic idea is taking a $Diff between the props and typeof the default props. I haven't kicked the tires thoroughly at all, but maybe it's a start.
@AndrewSouthpaw Unfortunately it's not a right way, too, because it makes components unsound
Hmm. How about combining $Diff and $Shape in an intersection?
Hmmm, looks good, I'll try to use it in real codebase and see if it works on more cases.
Thank you very much!
It works + we have React.ElementConfig now.
Most helpful comment
It works + we have React.ElementConfig now.