镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Tuples should be clonable with Array.prototype.slice() #4988

Description

@vjau

Let's say i define a tuple type like this :

type MyTuple = [number, number]

Now when i do this:

let a: MyTuple = [1, 2]
let b: MyTuple = a.slice();

The compiler complains that TS2322: Type 'number[]' is not assignable to type '[number, number]'. Property '0' is missing in type 'number[]'.

I think it should work, slice without argument (or slice(0) or even slice(0,2)) should allow to clone a tuple.

Activity

  1. DanielRosenwasser commented on Sep 27, 2015

    @DanielRosenwasser
    Member

    Great idea - after #4910 goes in we can add an overload in lib.d.ts so that slice with no arguments returns the this type.

  2. ahejlsberg commented on Sep 27, 2015

    @ahejlsberg
    Member

    Just added the necessary changes to #4910. When it goes in, all we need is the extra overload in lib.d.ts.

  3. modified the milestones: , TypeScript 1.7 on Oct 3, 2015
  4. DanielRosenwasser commented on Oct 3, 2015

    @DanielRosenwasser
    Member

    Actually, I'm not so sure about this anymore; if you subclass array, then you definitely aren't going to get the expected behavior when you .slice().

  5. mhegazy commented on Oct 3, 2015

    @mhegazy
    Contributor

    I would not say Subclassing array is the common scenario.

  6. 6 remaining items

  7. mhegazy commented on Oct 7, 2015

    @mhegazy
    Contributor

    So the right thing is to do what Daniel Rosenwasser (@DanielRosenwasser) suggested and have a new type to represent the Tuple that extends Array. one thing to note, we would not want to require users to update their library as they update the compiler (as some users have a hand crafted version of the library) so we need to come up with a solution that does not violate this constraint.

  8. sandersn commented on Oct 7, 2015

    @sandersn
    Member

    I need to go read the spec for tuple types and assignment. Right now I don't understand well enough how the type system supports it. I'll see if I can come up with a proposal afterwards.

  9. sandersn commented on Oct 8, 2015

    @sandersn
    Member

    After looking at the spec, the relevant section is 3.3.3. It gives an example of a named tuple type:

    interface KeyValuePair<K, V> extends Array<K | V> { 0: K; 1: V; }
    

    It also says that a type is said to be a tuple-like type if it has a property with the numeric name '0'. Combining these two, I guess we could change the spec to include an explicit tuple type that is the parent of all tuple types:

    interface TupleArray<T> extends Array<T> { 0: any }
    

    Then KeyValuePair becomes

    interface KeyValuePair<K,V> extends TupleArray<K | V> { 0: K, 1: V }
    

    The problem with this is that 0's type in TupleArray is any. If it's T, then KeyValuePair's must have a property 0: K | V, even though it should be 0: K. I think any is OK here because it represents what's going on with Array -- it's not a homogenous array anymore.

    Now we can take Daniel Rosenwasser (@DanielRosenwasser) 's proposal and put slice inside TupleArray. But to avoid promising that slice returns properties from tuple subclasses, per Anders Hejlsberg (@ahejlsberg), we can actually make it return TupleArray<T>:

    interface TupleArray<T> extends Array<T> {
        0: any;
        slice: TupleArray<T>;
    }

    The only hole here is that I don't know whether this satisfies Mohamed Hegazy (@mhegazy) 's constraint that users not update their lib.d.ts. Thoughts?

  10. DanielRosenwasser commented on Oct 17, 2015

    @DanielRosenwasser
    Member

    Assuming you meant slice(): TupleArray<T> that doesn't work because you lose the other numeric properties that make the tuple useful (i.e. 1, 2, etc.). You'd just end up with a type that has a property 0 whose type is the union of all types in the original tuple.

  11. sandersn commented on Nov 11, 2015

    @sandersn
    Member

    Closing for now -- we should revisit once we have variadic kinds for tuple types so that there is at least a chance to write a type like:

    interface Array<T> {
       slice<...U>(): ...U;
    }

    ...although I'm still not sure how to relate T and ...U here.

  12. Igorbek commented on Sep 21, 2016

    @Igorbek
    Contributor

    ...although I'm still not sure how to relate T and ...U here.

    You would not (T is a union of constituent types in ...U), unless tuples get first-class support like here #6229

  13. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptDomain: lib.d.tsThe issue relates to the different libraries shipped with TypeScriptRevisitAn issue worth coming back to

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions