This has bitten me a couple of times recently.
Here's the minimal repro case:
/* @flow */
const a = {
a: {i: 0},
b: {i: 1},
};
const x = "a";
const y: string = "c";
// This one can be inferred via the literal string
a[x].i + "A";
// This one should really be ?{i: number}
// but it seems to be (unknown)
a[y].i + "A";
If I add the hint {[k: string]: ?{i: number}}
onto the map then I get warned about nulls, but I lose the literal inference.
On a related note, I think the non-nullable {[k: string]: {i: number}}
type should only be allowed if every key in the keyspace is defined 馃槃
If you skip the redundant type annotation on y
it works as expected.
| |
| :-: |
This is interesting though.
It's unexpected behaviour that having a redundant annotations breaks type checking.
The redundant type annotation was just to hide the literal value from flow - in reality that's a value of type string coming from elsewhere in the program.
@glenjamin This behavior is expected according to the current design. The question is whether to allow bracket access on object types that are not declared as dictionary types (call these strict objects). We decided to be less strict here to allow seamless looping over keys of a strict object. Might revisit decision in the future.
But for now, you can use the following workaround: Use the type { a: { i: number }, b: { i: number }, [k: string]: ?{ i: number } }
on const a
to get what you want.