Why is there a thread error when using a switch statement to cycle through keys in an object?
This is obviously a contrived example, but I don't understand why the thread is an error in this case. The error I receive from the thread is causing the call map
. It says that mothod cannot be called on undefined.
You can see the error in the streaming editor here.
Two things I don't understand about are questions repeated in the code example as inline comments) i. Should I even check that foo[key]
is an array? II. Why does the thread error disappear if I change the first break statement to a return statement?
/* @flow */
type Foo = {
myArray?: Array<string>
};
function test(foo: Foo) {
Object.keys(foo).forEach(key => {
switch (key) {
case "myArray":
/**
QUESTION 1:
I shouldn't have to check that foo[key] is an array because I've told flow that when I do
have a key called myArray it going to be an array. If I remove this if statement
I get an error saying that I could be calling
*/
if (!Array.isArray(foo[key])) {
/**
QUESTION 2:
If I change this break statement to a return statement instead, flow linting passes and
it doesn't complain about the .map call below. Why?
*/
break;
}
const result = foo[key].map(s => {
return s + "1";
});
console.log(result);
break;
default:
break;
}
});
}
test({ myArray: ["foo"]});
test({});
source to share
QUESTION 1: You don't need to check the type of the array. Just check the value for null.
(Value type and result are for examples. They can be removed)
const value: ?Array<string> = foo[key];
if (value == null)
break;
const result: Array<string> = value.map(s => {
return s + "1";
});
QUESTION 2: If the value is null, no stream errors occur. It is likely that flow handles break and return assertions in different ways.
Better to prefer break
over return
inside switch
inside loop
. If forEach is refactored for loop (...) then behavior changes return
.
PS Object.assign
type definition seems to be broken
https://github.com/facebook/flow/issues/1149
source to share
I think this is due to the fact that Flow cannot be sure that it is foo
not mutating from outside the function. Having created a local shallow copy foo
everything is fine.
/* @flow */
type Foo = {
myArray?: Array<string>
};
function test(foo: Foo) {
const localFoo = Object.assign({}, foo);
Object.keys(localFoo).forEach(key => {
switch (key) {
case "myArray":
const result = localFoo[key].map(s => {
return s + "1";
});
console.log(result);
break;
default:
break;
}
});
}
test({ myArray: ["foo"]});
test({});
source to share