I have a container component and it's props type with children property:
type Props = {
children: Array<React.Element<any>> | React.Element<any>,
settings: string | Object
};
Container can contain the only one React.Element or multiple and depends on that it should choose the right operation.
In the render function I have something like that:
const children = this.props.children;
if ( _.isArray(children) ) {
return _.map(children, (child, key) => checkListComponent(child, key));
}
else if ( _.isObject(children) ) {
return checkListComponent(children);
}
The main function is that:
const checkListComponent = (child: React.Element<any>, key) => {
return child.props.list
? React.cloneElement(child, key ? { options, key } : { options })
: child;
};
And after all I get a Flow error in else if
return checkListComponent(children);
Flow: array type. This type is incompatible with the expected param type of React$Element.
It seems to ignore possible type of non Array for the children prop. I found issue on Github about union Array and Object type but there is nothing.
Is there any solution for that situation?
UPD:
The same problem I have with props.settings, it can be an API url to fetch settings object from the server or a direct settings object. When I call an axios.get(settings) (obviously check before that props.settings is a string for now) Flow ignores possible string type and complains that Object given instead of string. BUT in the next line when I check settings for an object type and set container state
this.setState({ settings: this.props.settings });
It complains that String given instead of Object.
How it is possible and what can I do with that? I can but don't want to have two different props for settings API and Object. And definitely this is impossible for the props.children part of a problem.
Flow has no way to know that _.isArray
returning true
means that children
is an array, and the same applies to _.isObject
. Your code should work as
const children = this.props.children;
if (Array.isArray(children) ) {
return children.map((child, key) => checkListComponent(child, key));
} else {
return checkListComponent(children);
}
since Array.isArray
is standard and Flow can know that in the else
block children
must be the the non-array type in your union.