Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Type inference could be smarter with mixed Array types #2507

Closed
bgeihsgt opened this issue Sep 21, 2016 · 8 comments
Closed

Type inference could be smarter with mixed Array types #2507

bgeihsgt opened this issue Sep 21, 2016 · 8 comments

Comments

@bgeihsgt
Copy link

Flow Version: 0.32.0

Consider the following example:

// @flow

function foo(arr: Array<number> | Array<string>) {

}

foo([1, 2]);

I'd expect the type inference to know that [1, 2] is an array of numbers and accept the foo([1, 2]) call, but instead I get this error:

  7: foo([1, 2]);
         ^^^^^^ array literal. Could not decide which case to select
  3: function foo(arr: Array<number> | Array<string>) {
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union type
  Case 1 may work:
    3: function foo(arr: Array<number> | Array<string>) {
                         ^^^^^^^^^^^^^ array type
  But if it doesn't, case 2 looks promising too:
    3: function foo(arr: Array<number> | Array<string>) {
                                         ^^^^^^^^^^^^^ array type
  Please provide additional annotation(s) to determine whether case 1 works (or consider merging it with case 2):
    7: foo([1, 2]);
           ^^^^^^ inferred union of array element types (alternatively, provide an annotation to summarize the array element type)

Obviously I can work around this by adding annotations, but was curious: Is this a solvable problem without annotations or is this just the nature of the complicated problem inferring mixed types?

@jkk
Copy link

jkk commented Sep 30, 2016

I'm running into this with React Native's Animated.Value.interpolate() outputRange key, which has a signature of (Array<number> | Array<string>).

@bgeihsgt
Copy link
Author

@jkk That's where I originally saw this as well.

@vkurchatkin
Copy link
Contributor

Looks like a bug, case 2 isn't really promising

@vkurchatkin vkurchatkin added the bug label Nov 9, 2016
@acarl005
Copy link

Similar issue with a union type of an array.

type TerritoryCode = 'US' | 'FR' | 'RE' | //...

type Track = {
  territories: Array<TerritoryCode> | TerritoryCode
  //...
}

const track: Track = {
  territories: [ 'US', 'FR' ]
}

I get the following error:

test-run-v2.js:99
 99:         territories: [ 'US', 'FR' ]
                          ^^^^^^^^^^^^^^ array literal. Could not decide which case to select
122:   territories: Array<TerritoryCode> | TerritoryCode
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ union type. See: src/flow-types/input-object.js:122
  Case 1 may work:
  122:   territories: Array<TerritoryCode> | TerritoryCode
                      ^^^^^^^^^^^^^^^^^^^^ array type. See: src/flow-types/input-object.js:122
  But if it doesn't, case 2 looks promising too:
  122:   territories: Array<TerritoryCode> | TerritoryCode
                                             ^^^^^^^^^^^^^ TerritoryCode. See: src/flow-types/input-object.js:122
  Please provide additional annotation(s) to determine whether case 1 works (or consider merging it with case 2):
   99:         territories: [ 'US', 'FR' ]
                            ^^^^^^^^^^^^^^ inferred union of array element types (alternatively, provide an annotation to summarize the array element type)

@gokulbharathi
Copy link

Do any one have solution for @acarl005 example code, i have a similiar situation. How can we provide the type of array while initializing the array.

@mdsib
Copy link

mdsib commented Jun 15, 2018

@gokulbharathi : I tested it out on 0.73.0, and it looks like Flow can handle selecting the correct type in the union of a union and an array. But it still errors out on the union of 2+ arrays. I ended up casting the array like so:

type ThingArray = Array<number> | Array<boolean>;

type ThingObj = {
  arrayOfThings: ThingArray
};

const thingObjInstance = {
  arrayOfThings: ([1, 2, 3]: Array<number>)
};

@jrsinclair
Copy link

Explicitly annotating the array type isn't really a great workaround. ☹️ But thanks for sharing @mdsib. It appears to be the only option available.

@SamChou19815
Copy link
Contributor

This now works under inference_mode=lti

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants