GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — tuple type don't check number of elements · Issue #5259 · microsoft/TypeScript

tuple type don't check number of elements #5259

New issue
Copy link
New issue
Copy link
Closed
Closed
tuple type don't check number of elements#5259
Copy link
Assignees
sandersn
Labels
BugA bug in TypeScriptA bug in TypeScriptBy DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead

Description

@co-dh
Hao Deng (co-dh)
opened on Oct 14, 2015
Issue body actions

The following compiles,

    var foo:[string, string] = ['','', '', '']

while this one not:

    var foo:[string, string] = ['','', '', 1]

The first one should not compiles, since the initializer has 3 elements while the type says 2.

Activity

  1. sandersn commented on Oct 14, 2015

    @sandersn
    Nathan Shively-Sanders (sandersn)
    on Oct 14, 2015
    Member
    More actions

    Tuples are basically objects with numeric properties. So foo: [string, string] is like saying foo: {0: string, 1: string}. The value you assign to foo has an extra property '2', but that's OK in Typescript.

    The second doesn't compile for a different reason, which is just that the array ['', '', '', 1] is typed as (number | string)[], and number is not compatible with any of the types in [string, string] -- even though the number doesn't occur until the third element.

    The first reason basically makes sense to me, although it would be nice if Typescript had better checking here.

    The second reason is a side effect of using arrays to represent tuples, and is a bit unfortunate. For example, this doesn't compile either:

    var bar: (number | string)[] = [1, 2, ''];
    var foo: [number, number, string] = bar; // (number | string)[] is not assignable to [number, number, string]
    
    var baz: [number, number, string] = [1, 2, '']; // OK!
  2. seanfreiburg commented on Oct 16, 2015

    @seanfreiburg
    Sean Freiburg (seanfreiburg)
    on Oct 16, 2015
    More actions

    Second doesn't compile because 1 isn't a string. You gave it a type of [string,string].

  3. Mohamed Hegazy (mhegazy)
    added
    QuestionAn issue which isn't directly actionable in codeAn issue which isn't directly actionable in code
    on Oct 16, 2015
  4. sandersn commented on Oct 16, 2015

    @sandersn
    Nathan Shively-Sanders (sandersn)
    on Oct 16, 2015
    Member
    More actions

    According to the spec section 3.3.3, the type [number, string] is equivalent to an interface that extends Array:

    interface NSPair extends Array<number | string> { 0: number, 1: string }
    

    The unfortunate side effect of this is that extra elements in a tuple assignment are ignored, but only if they are of a type that is already present in the tuple. That's because [1, "foo", 2]: (number | string)[], which NSPair extends, but [1, "foo", false]: (number | string | boolean)[], which it does not.

    I think this is a bug in the spec, but I'm not at all sure how to fix it. Maybe an ad-hoc rule that says the lengths have to match, or maybe there's an existing way to fix it in the language.

    Reacted by Will
  5. Nathan Shively-Sanders (sandersn)
    added
    BugA bug in TypeScriptA bug in TypeScript
    on Oct 16, 2015
  6. Mohamed Hegazy (mhegazy)
    removed
    QuestionAn issue which isn't directly actionable in codeAn issue which isn't directly actionable in code
    on Oct 28, 2015
  7. Mohamed Hegazy (mhegazy)
    assigned
    Nathan Shively-Sanders (sandersn)
    on Oct 28, 2015
  8. JsonFreeman commented on Dec 3, 2015

    @JsonFreeman
    Jason Freeman (JsonFreeman)
    on Dec 3, 2015
    Contributor
    More actions

    Tuples are already quite unsafe because you can do the following:

    var tuple: [number, string] = [0, ""];
    for (var i in tuple) {
        tuple[i] = ""; // Succeeds because string is assignable to number | string
    }
    tuple[0]; // type is number, but should be string

    I think the goal of giving the user the right type needs to be relaxed for tuples, relative to other parts of the language. On the one hand, there are no restrictions on what users can do with tuples, but on the other hand, users may make strong assumptions about what the tuple will contain at each index (that's what makes it a tuple). This disconnect between expectation and reality should probably be addressed more broadly if any changes to the type checking rules for tuples are considered.

  9. ahejlsberg commented on Dec 8, 2015

    @ahejlsberg
    Anders Hejlsberg (ahejlsberg)
    on Dec 8, 2015
    Member
    More actions

    This isn't a bug, it is working as designed. Our view is that tuple is an array for which we have static knowledge of the individual types of the first N elements and for which the element type is the union of the types of those N elements. We allow more than N elements to be present (since there's really not much we can do to prohibit it), but we do require those elements to have a compatible type.

    Reacted by Alan Boglioli
    Reacted by Arnau Orriols and Thanh Ngo
  10. Anders Hejlsberg (ahejlsberg)
    added
    By DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead
    on Dec 8, 2015
  11. Anders Hejlsberg (ahejlsberg)
    closed this as completedon Dec 8, 2015
  12. mortb commented on Jun 28, 2016

    @mortb
    mortb
    on Jun 28, 2016
    More actions

    Must say I feel a bit sad about this.

    I felt a bit excited when I read about tuples in the typescript handbook:
    https://www.typescriptlang.org/docs/handbook/basic-types.html#tuple
    When realizing that there is no checking on the number of array elements the tuple feature doesn't seem as attractive as it did in my first impression.
    After a second read in the typescript handbook I see that this limitation it is mentioned:

    When accessing an element outside the set of known indices, a union type is used instead

    But I was expecting something to use like C# tuples: (dotnet/roslyn#347)
    Oh well...

  13. aboglioli commented on Apr 4, 2017

    @aboglioli
    Alan Boglioli (aboglioli)
    on Apr 4, 2017
    More actions

    Tuples should have a fixed size or number of elements. That's a property:
    Properties of tuples

  14. RyanCavanaugh commented on Apr 4, 2017

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Apr 4, 2017
    Member
    More actions

    Identical is not the same as subtype.

  15. wclr commented on Apr 7, 2017

    @wclr
    Alex (wclr)
    on Apr 7, 2017
    More actions

    So there is no way any way to fixate number of elements of the tuple or list in typing? To me this is a big disadvantage.

  16. RyanCavanaugh commented on Apr 7, 2017

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Apr 7, 2017
    Member
    More actions
    type fixed = [number, number] & { 2: void };
    // Error
    var x: fixed = [3, 3, 3];
    Reacted by Zack Mulgrew and Carl Patenaude-Poulin
  17. wclr commented on Apr 7, 2017

    @wclr
    Alex (wclr)
    on Apr 7, 2017
    More actions

    but it doesn't work with 2 either:

    type fixed = [number, number] & { 2: void };
    // Error
    var x: fixed = [3, 3];

    Type '[number, number]' is not assignable to type 'fixed'.
    Type '[number, number]' is not assignable to type '{ 2: void; }'.
    Property '2' is missing in type '[number, number]'.

  18. RyanCavanaugh commented on Apr 7, 2017

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Apr 7, 2017
    Member
    More actions

    Sorry

    type fixed = [number, number] & { 2?: void };
    // Error
    var x: fixed = [3, 3, 3];
    // OK
    var y: fixed = [3, 3];
    Reacted by Zack Mulgrew and Evan Wieland
  19. wclr commented on Apr 7, 2017

    @wclr
    Alex (wclr)
    on Apr 7, 2017
    More actions

    Ryan Cavanaugh (@RyanCavanaugh) cool, thank you! Btw when was this feature added?

  20. RyanCavanaugh commented on Apr 7, 2017

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Apr 7, 2017
    Member
    More actions

    That's worked for as long as intersection types (or tuples? whichever came first) have existed

  21. arnauorriols commented on Nov 16, 2017

    @arnauorriols
    Arnau Orriols (arnauorriols)
    on Nov 16, 2017
    More actions

    This isn't a bug, it is working as designed. Our view is that tuple is an array for which we have static knowledge of the individual types of the first N elements and for which the element type is the union of the types of those N elements. We allow more than N elements to be present (since there's really not much we can do to prohibit it), but we do require those elements to have a compatible type.

    This is the boldest "it's not a bug, it's a feature" case I've seen in years. Respect.

    We allow more than N elements to be present (since there's really not much we can do to prohibit it), but we do require those elements to have a compatible type.

    Maybe it's not simple to prohibit the number of items a tuple contains, but what about reading the tuple? Could be prohibited using an index larger than the tuple size?

    const t: [number, number] = [1, 2, 3];  // Works, apparently not possible to prohibit consistently
    t[1];  // works
    t[2];  // Error, [number, number] only has 2 elements

    Regarding prohibiting the number of elements a tuple has, I imagine you say it's not possible because of the mutable nature of the arrays in javascript. However, the majority of languages that contain the tuple data structure define them as immutable, even in those languages prone to mutability, like Python. Have you considered making tuples immutable? That could be done easily, and would allow typescript to stop saying that a tuple has unlimited size by design...

  22. RyanCavanaugh commented on Nov 17, 2017

    @RyanCavanaugh
    Ryan Cavanaugh (RyanCavanaugh)
    on Nov 17, 2017
    Member
    More actions

    Arnau Orriols (@arnauorriols) see #17765

    Reacted by Arnau Orriols
    Reacted by Arnau Orriols
  23. microsoft
    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

Assignees

  • @sandersn
    Nathan Shively-Sanders (sandersn)

Labels

BugA bug in TypeScriptA bug in TypeScriptBy DesignDeprecated - use "Working as Intended" or "Design Limitation" insteadDeprecated - use "Working as Intended" or "Design Limitation" instead

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    You are visitor 01402503 — GeezerVison does not store the pages you look up.
    Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.