TypeScript: tuple type don't check number of elements

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.

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 16 (9 by maintainers)

Most upvoted comments

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.

Sorry

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

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.