ObjMap return value or function

Viewed 160

I don't understand why this is not working. I expect $ObjMap to require that the object return the value, or a function that returns that value. See the comment in the code. Anyone know how to make this work?

type TObj = {|
  a: number,
  b: string,
  c: boolean,
|};

type Extract = <V>(V) => (() => V) | V

type TType = $ObjMap<TObj, Extract>

function a (): string {
  return 'a';
}

// Expect a to have an error as it is a function that returns a string.
// $ObjMap states that it must be either a number, or a function that returns 
// a number.
const t: TType = {
  a,
  b: 'v',
  c: true,
};

https://flow.org/try/#0C4TwDgpgBAKg8gIwFZQLxQN4B8BQUoCGAXFAHYCuAtghAE4A0eUCJAzsLQJakDmj+AYxIIA9iIA2EAqUZYAvgG4cOUJCgBRAB4cCA4GigAeAGoA+ABTGAlGlNRz5m6jvWoWKMeWroMGOGjoACSISACyBGCG8Mj0Gtq0usCmygBm5KR6nCKkhPZWbBzcPJhMtBDA5LQ5AOQE1UpyygLZ7FDAJL7+BhhMxIT8zCTVAG7VA0JttOQQjIpAA

1 Answers

This seems to me like a limitation/bug in the implementation. Here's why:

If we change Extract such that it would expect the primitives only, we establish a baseline by observing that everything works as expected.

type Extract = <V>(V) => V
19:   a: a,
         ^ Cannot assign object literal to `t` because function [1] is incompatible with number [2] in property `a`. [incompatible-type]
    References:
    11: function a (): string {
        ^ [1]
    2:   a: number,
            ^ [2]

Next we modify Extract to only accept functions with a return type of number or the respective expected value.

type Extract = <V>(V) => ((() => number) | V)

Now we observe your expected behavior, error on a

19:   a: a,
         ^ Cannot assign object literal to `t` because string [1] is incompatible with number [2] in the return value of property `a`. [incompatible-type]
    References:
    11: function a (): string {
                       ^ [1]
    7: type Extract = <V>(V) => ((() => number) | V)
                                        ^ [2]

However if we change the accepted type from number to string the error goes away, which means everything is working fine up to this point.

Finally when we replace number with V the error disappears. This makes me think the interpreter has trouble resolving and falls back to any as a default.

I would expect such problems with static analysis, it is called static for a reason.

Disclaimer: Everything that I said above are just thoughts and assumptions, I'm posting in an attempt to help, and may be complete garbage, in which case I apologize.

Related