Reputation: 4615
I have following error from flow in one before the last line of function getRowData:
message: 'Cannot call
getRow
withel.arr
bound todata
because: Either propertyarr
of unknown type [1] is incompatible with array type [2]. Or propertyarr
of unknown type [1] is incompatible with string [3]. (References: [1] [2] [3])' at: '60,44' source: 'flow' code: 'undefined'
This error is disappearing only if I change Array<string>
in type UserProps
to Array<mixed>
, but I'd like to stay with the array of strings.
I don't understand why I get this error. I explicitly set data.audio
and data.chat
to Array<string>
. Any help will be highly appreciated!
type UserProps = {
name: string,
audio: Array<string>,
chat: Array<string>,
enableChat: boolean,
enableAudio: boolean,
status: string,
};
const getRow = (key, data: string[] | string, style = {}) => {
const text = Array.isArray(data) ? data.join(", ") : data;
return (
<TableRowColumn
key={`row-${key}`}
style={{ whiteSpace: "pre-wrap", ...style }}
>
{text}
</TableRowColumn>
);
};
const getRowData = (data: UserProps) =>
[
data.name,
data.status,
{
arr: data.audio,
style: { color: data.enableAudio ? "green" : "red" }
},
{ arr: data.chat, style: { color: data.enableChat ? "green" : "red" } }
].map(
(el, i) =>
el && el.arr && el.style ? getRow(i, el.arr, el.style) : getRow(i, el) // error in el.arr !!!!!
);
Upvotes: 0
Views: 1324
Reputation: 37978
Error is a bit confusing, but the problem is that flow fails to refine the el
type. What you can do to is slightly change the refinement:
typeof el === 'string' ? getRow(i, el) : getRow(i, el.arr, el.style)
You can try it here
Upvotes: 1
Reputation: 3201
getDataRow
does not have an annotated return type, so its implied by the return value, which is an array consisting of string, string, object, object, which is then passed through map
(which returns the same type as the input). el
in the map
callback is therefore string | object
.
Flow can't determine if arr
is a property of string or object. It could be undefined (I've found problems with flow's interpretation of compound logical tests like you have in el && el.arr && el.style
. If you spell them out as if
statements they work as expected, but logical &&
and ||
seems problematic).
As a result, flow thinks el.arr
is not compatible with the second argument of getRow
which requires string[] | string
.
You'd need to determine the type of el
before accessing the properties for flow to be happy. Testing for the presence of members arr
and style
does not do that (although you might want to look at Disjoint Unions as a way of doing so, if your types are malleable, but I think that's wouldn't work in this case because you have no option but to use the stock definition of string
).
As a side note, whilst the shorthand array syntax ({type}[]
) can be convenient, it can be confusing with optional or maybe values before you have less scope for where the ?
goes. As a result, I have opted to use the longhand Array<{type}>
syntax. There's more in the docs on the subject.
Upvotes: 1