This works:
// @flow
function foo(data: { [key: string]: string } | number): Array<string> {
if (typeof data === "object") {
return fooWithObject(data);
}
return ["1"];
}
function fooWithObject(data: { [key: string]: string }): Array<string> {
return Object.keys(data).map(k => data[k]);
}
console.log(foo(1));
console.log(foo({"1": "show", "2": "me"}));
However, this is broken:
// @flow
function foo(data: { [key: string]: string } | number): Array<string> {
if (typeof data === "object") {
return Object.keys(data).map(k => (data: Object)[k]);
}
return ["1"];
}
console.log(foo(1));
console.log(foo({"1": "show", "2": "me"}));
with error:
5: return Object.keys(data).map(k => (data: Object)[k]);
^ number. This type is incompatible with
5: return Object.keys(data).map(k => (data: Object)[k]);
^ object type
How can I help fix?
It's not broken, Flow is pessimistic about refinements. In your case you might change the data reference, pointing to a number
function foo(data: { [key: string]: string } | number): Array<string> {
if (typeof data === "object") {
return Object.keys(data).map(k => {
data = 1
// return data[k]
return 'evil code that typechecks'
});
}
return ["1"];
}
A way to help Flow keep a refinement is to use a const binding (docs)
function foo(data: { [key: string]: string } | number): Array<string> {
if (typeof data === "object") {
const o = data // <= fix
return Object.keys(o).map(k => o[k]);
}
return ["1"];
}
Maybe surprisingly another way to fix the error is to set the option experimental.const_params=true in .flowconfig (which prevents argument reassignments)
Thanks for the information! Apologies for filing an issue :)
In the first case can we have flow take note of where variables are reassigned in the AST to accurately track type information?
Haven't delved under the hood yet and was wondering whether, if all type cases have been checked, we can safely refine the types in these cases because there has been no reassignment?
Most helpful comment
Maybe surprisingly another way to fix the error is to set the option
experimental.const_params=truein.flowconfig(which prevents argument reassignments)