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

Wrong type inferred by returning a tuple #25516

Closed
MastroLindus opened this issue Jul 9, 2018 · 9 comments
Closed

Wrong type inferred by returning a tuple #25516

MastroLindus opened this issue Jul 9, 2018 · 9 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@MastroLindus
Copy link

MastroLindus commented Jul 9, 2018

TypeScript Version: 3.0.0-dev.20180707

Code

  const a: Array<[string, boolean]> = ["foo", "baz"].map(item => [item, !!item]);
  const b: Array<[string, boolean]> = ["foo", "baz"].map(item => { const value: [string, boolean] = [item, !!item]; return value;} );

Expected behavior:
Both expressions should be allowed
Actual behavior:
assignment for b works, assignment for a doesn't, as the compiler starts infering that the type for [item, !!item] is Array<string | boolean>.

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript In Discussion Not yet reached consensus labels Jul 9, 2018
@RyanCavanaugh
Copy link
Member

It's not wrong, it's just less precise than it should be.

I think this is fixable by improving the contextual type -> return type expression inference?

@jscheiny
Copy link

jscheiny commented Aug 2, 2018

Another example where a tuple inference would be desirable is in f0 below:

declare function f0<T extends any[]>(args: T): T;
declare function f1<T extends any[]>(...args: T): T;

f0(["a", 1]); // (string | number)[]
f1("a", 1); // [string, number]

This is currently blocking a typesafe implementation of Promise.all without overloads.

@wjohnsto
Copy link

wjohnsto commented Aug 6, 2018

👍

Yes, the update to tuples to allow for f1 in @jscheiny's comment is great! Unfortunately for some of the Promise functions it doesn't work since the argument is actually an array argument, not rest arguments.

@rrousselGit
Copy link

This is not only related to functions. Variables are affected too:

    let test1: [number, string];
    const a = [42, ''];

    test1 = a; // error

Type '(string | number)[]' is not assignable to type '[number, string]'.
Property '0' is missing in type '(string | number)[]'.

@RyanCavanaugh
Copy link
Member

@rrousselGit that is the intended behavior, because this code is legal:

    let test1: [number, string];
    const a = [42, ''];
    a[0] = "hello"; // Does not affect type system

    test1 = a; // Unsound to allow

@CorayThan
Copy link

CorayThan commented Aug 28, 2018

This issue prevents normal creation of ES6 maps. This valid JS:

var kvArray = [['key1', 'value1'], ['key2', 'value2']];
var myMap = new Map(kvArray);

Doesn't compile due to Argument of type 'string[][]' is not assignable to parameter of type 'ReadonlyArray<[any, any]>'..

But if you just cast it to the right type it works fine:

const kvArray = [['key1', 'value1'], ['key2', 'value2']]
const myMapFromAny = new Map(kvArray as Array<[string, string]>)

At least I think this is the same issue. Didn't want to make a duplicate issue.

@MattiasMartens
Copy link

@rrousselGit By default, array literal declarations are given an array type, not a tuple type. There is a proposal to change this, and if you have a strong opinion to share I'd recommend chiming in because it is still in the feedback stage: #16896

@austonpramodh
Copy link

austonpramodh commented Sep 25, 2019

+1
for different return types for different promises in promise.all

@weswigham
Copy link
Member

Randomly found this while looking through some other stuff - the OP has been fixed, at least as of TS 5.0. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

9 participants