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

mapping over an array of tuple types does not give the correct type #11312

Closed
mattyork opened this issue Oct 3, 2016 · 5 comments
Closed

mapping over an array of tuple types does not give the correct type #11312

mattyork opened this issue Oct 3, 2016 · 5 comments
Labels
Duplicate An existing issue was already created

Comments

@mattyork
Copy link

mattyork commented Oct 3, 2016

TypeScript Version: 2.0.3

Code

The map callback in the code below is the identity function.

let arr: Array<[number, number]> = [[1, 2]]

let mappedArr: Array<[number, number]> = arr.map(([x, y]) => {
    return [x, y];
})

Expected behavior: mappedArr is of type Array<[number, number]>. Compilation works.

Actual behavior: Doesn't work. Error message:

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

TypeScript playground link

@kitsonk
Copy link
Contributor

kitsonk commented Oct 3, 2016

Tuples are never inferred. On the return, you have to be explicit:

let arr: Array<[number, number]> = [[1, 2]]

let mappedArr: Array<[number, number]> = arr.map(([x, y]) => {
    return <[number, number]> [x, y];
});

... or ...

let arr: Array<[number, number]> = [[1, 2]]

let mappedArr: Array<[number, number]> = arr.map(([x, y]): [number, number] => {
    return [x, y];
});

But of course then you don't have to be explicit about the left hand side then:

let arr: Array<[number, number]> = [[1, 2]]

let mappedArr = arr.map(([x, y]): [number, number] => {
    return [x, y];
});

@gcnew
Copy link
Contributor

gcnew commented Oct 3, 2016

You can also manually augment map as proposed in #11252.

@kitsonk
Copy link
Contributor

kitsonk commented Oct 3, 2016

Which means this is dupe of #6574, I had forgotten.

@calebegg
Copy link

I don't think this is a dupe; that issue is about mapping tuples to tuples (and also, it's fixed). This is about mapping arrays of tuples to arrays of tuples.

The issue could be more succinctly stated as: "Tuple return types are not inferred". Here's a simple repro case:

http://www.typescriptlang.org/play/#src=function%20foo(x%3A%20number%2C%20y%3A%20string)%20%7B%0D%0A%20%20%20%20return%20%5Bx%2C%20y%5D%3B%0D%0A%7D

(note that the return type is (number | string)[] instead of [number, string])

The fact that arrow functions therefore can't map tuples to tuples is just a consequence of that.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 29, 2016

This is another manifestation of #11152.

map is declared as:

map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];

so you see U is only inferred from the return type of the callback function. since tuple types are never inferred unless there is a contextual type (which in this case there is none), a regular array type is inferred for U, then the assignment check is done, and it fails.

The piece that is missed here, is we know that the U[] will be assigned to mappedArr, and we should use this as a contextual type. #11152 tracks propagating using the return type of the contextual signature if one exists as another location for inference.

@mhegazy mhegazy added the Duplicate An existing issue was already created label Oct 29, 2016
@mhegazy mhegazy closed this as completed Oct 31, 2016
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

5 participants