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

Cloning a tuple turns it into an array #16503

Closed
Zarel opened this issue Jun 13, 2017 · 8 comments
Closed

Cloning a tuple turns it into an array #16503

Zarel opened this issue Jun 13, 2017 · 8 comments
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@Zarel
Copy link

Zarel commented Jun 13, 2017

TypeScript Version: every version tested (from 2.3.0 to 2.5.0-dev.20170613)

Code

type Tuple = [number, number];
let t1: Tuple = [1, 2];
let t2: Tuple = t1.slice();
let t3: Tuple = t1.slice(0);
let t4: Tuple = [...t1];

Expected behavior:
No error

Actual behavior:

test-slice.ts(3,5): error TS2322: Type 'number[]' is not assignable to type '[number, number]'.
  Property '0' is missing in type 'number[]'.
test-slice.ts(4,5): error TS2322: Type 'number[]' is not assignable to type '[number, number]'.
test-slice.ts(5,5): error TS2322: Type 'number[]' is not assignable to type '[number, number]'.

array.slice() and array.slice(0) and [...array] are common idiomatic ways to shallow-clone an array. Unfortunately, this loses the tuple type information.

I don't know how easy this would be to fix, but even something like supporting only tuples below a certain length (by hardcoding [T1, T2] => [T1, T2] type signatures for Array#slice) would be a pretty big improvement for my own use-case.

@mhegazy
Copy link
Contributor

mhegazy commented Jun 13, 2017

I suppose we can make Tuple extend from a new Tuple interface instead of Array, and make that return this in a punch of places.

@thw0rted
Copy link

For some reason #4988 was closed but this was left open. I just want one correct, non-verbose way to clone a tuple.

@thw0rted
Copy link

I don't remember exactly what led me to post this a few months ago but as of now it looks like slice does return the same tuple. Unfortunately, so does slice(0,1) so you can easily give yourself a tuple that's actually shorter than should be guaranteed. Is that intentional?

@y-nk
Copy link

y-nk commented May 19, 2022

@thw0rted
Copy link

I don't remember the circumstances when I posted that, but it looks like I was probably wrong. I spent a minute trying different versions of the playground and all the ones I can find behave the same way -- slice returns an array.

@RyanCavanaugh
Copy link
Member

Spread works now, which seems sufficient + idiomatic, and I think we don't have any good mechanisms to hardcode slice in a satisfying way.

@thw0rted
Copy link

Thanks Ryan, is this in the docs anywhere? I can't find anything about spread on the Tuple page, or anything about tuples on the Spread page.

I'm trying to understand how implied types work with spread, specifically. In this example, you can explicitly type an assignment from a spread-clone without any errors, but if you don't give any hints, it still winds up as a non-tuple array.

I'd still like to have a built-in that copies a tuple and always treats the result as the same tuple signature; I guess I could write a lightweight wrapper that just uses spread if I have to.

@RyanCavanaugh
Copy link
Member

This is a facet of contextual typing: array literals get checked as tuples if contextually typed by a tuple type.

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

5 participants