Reputation: 306
I am having some issues trying to use the "disjoint unions" created by flow. Apparently flow tries to mash them together, but I still don't actually know why.
type Single = {|
type: 'single',
value?: string,
onChange: (value?: string) => void, // line:47
|};
type Multiple = {|
type: 'multiple',
value?: string[],
onChange: (value: string[]) => void, // line:53
|}
type Props = Single | Multiple;
Having the flow definitions from above, I should be able to do this without any error, right?
// (Yes, it is react)
function someFunc(receivedValues?: string[]) {
// ...
// value, type and onChange were pulled from "props: Props"
if (type === 'single') {
if (receivedValues && receivedValues.length) {
onChange(receivedValues[0]); // line:110
}
} else if (type === 'multiple') {
if (receivedValues && receivedValues.length) {
const casted: string[] = value && value.length ? value : [];
onChange(casted.concat(receivedValues)); // line:115
}
}
//...
}
But flow throws me multiple errors:
Error: file.jsx:110
110: onChange(receivedValues[0]);
^^^^^^^^^^^^^^^ string. This type is incompatible with the expected param type of
53: onChange: (value: string[]) => void,
^^^^^^^^ array type
Error: file.jsx:114
114: const casted: string[] = value && value.length ? value : [];
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string. This type is incompatible with
114: const casted: string[] = value && value.length ? value : [];
^^^^^^^^^^ array type
Error: file.jsx:115
115: onChange(casted.concat(receivedValues));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ array type. This type is incompatible with the expected param type of
47: onChange: (value?: string) => void,
^^^^^^^ string
For what I understand it is just merging Single
and Multiple
, and it is not making the selection of one of them. Does anyone have any idea on how to fix this?
Upvotes: 2
Views: 407
Reputation: 161677
Since you've pulled the values off of the object already, checking type
has no effect on narrowing down the type of value
and onChange
. Your code will work if you work with the object directly:
function someFunc(receivedValues?: string[]) {
var obj: Props = { type: 'single', onChange: () => {} };
if (obj.type === 'single') {
if (receivedValues && receivedValues.length) {
obj.onChange(receivedValues[0]);
}
} else if (obj.type === 'multiple') {
if (receivedValues && receivedValues.length) {
const casted: string[] = obj.value && obj.value.length ? obj.value : [];
obj.onChange(casted.concat(receivedValues));
}
}
}
or only destructure the values off the object after refining the type.
function someFunc(receivedValues?: string[]) {
var obj: Props = { type: 'single', onChange: () => {} };
if (obj.type === 'single') {
const { onChange } = obj;
if (receivedValues && receivedValues.length) {
onChange(receivedValues[0]);
}
} else if (obj.type === 'multiple') {
const { onChange, value } = obj;
if (receivedValues && receivedValues.length) {
const casted: string[] = value && value.length ? value : [];
onChange(casted.concat(receivedValues));
}
}
}
Upvotes: 3