Flow: Flow incorrectly reporting possibly undefined value

Created on 1 Nov 2016  路  6Comments  路  Source: facebook/flow

This code

// @flow

type T = {
    s? : string
}

function f(t:T) {
    if (t.s == null){
        return "";
    }

    if (t.s.indexOf("foo") != -1){
        return "bar";
    }

    return t.s[0];
}

gives me this error

js/test.js:21
 21:    return t.s[0];
               ^^^^^^ access of computed property/element. Computed property/element cannot be accessed on possibly undefined value
 21:    return t.s[0];
               ^^^ undefined

If I replace condition with if (t.s.length < 2) or leave only last return everything works great. Some other cases:
if (t.s.charCodeAt(0) != 13) - bad
if (t.s.charAt(0) != 'a') - bad
if (t.s.substr(0) != 'a') - bad
if (t.s[0] != 'a') - good

That's flow 0.34.0 on linux.

not a bug refinements

All 6 comments

And if I remove T completely, and make it function f(s?:string) work fine also.

This is because calling functions (such as indexOf) can potentially invalidate previous checks. Before you check some value you can assign it to local const to avoid this.

Yeah, damned pessimistic calls. But why, especially for internal types? Anyway every property can be hidden by getter and/or Proxy, and trigger function call.

Just ran into this with .test on regular expressions with:

opts.ignoreCustomPatterns.test(basename) || opts.ignoreCustomPatterns.test(path)

It seems silly that this is applied to builtin types, as they functionality should be guaranteed.

At least, the error message should indicate that this potential changing of value is the cause - as I just spent an hour thinking this was an issue with my type definitions, rather than with this crazyness.

This is because calling functions (such as indexOf) can potentially invalidate previous checks. Before you check some value you can assign it to local const to avoid this.

Yeah, I follow this and the flow stop giving this error.

Was this page helpful?
0 / 5 - 0 ratings