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({});

      

+3


source to share


2 answers


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";
});

      

try flow example



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

+2


source


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({});

      

+1


source







All Articles