Typescript: Incompatibility between Tuple type and Array type

Created on 27 Feb 2019  ·  6Comments  ·  Source: microsoft/TypeScript

let a: [number, number];
const b = [1,2];
a = b; // Type 'number[]' is missing the following properties from type '[number, number]': 0, 1ts(2739)

Same error with any array lenghs:

let a: [number, number, number];
const b = [1,2,3];
a = b; // Type 'number[]' is missing the following properties from type '[number, number, number]': 0, 1, 2ts(2739)

I can't set array with fixed length. Just why? Why it isn't working? Seems like a bug.

Working as Intended

Most helpful comment

Yes. Variables in TypeScript have the same read type as write type. This is an intentional decision that makes things more predictable.

Consider if this were allowed - this example illegally prints 3 instead of 2

function fn(x: { a: [number, number] }) {
  setTimeout(() => console.log(x.length);
}
const obj = { a: [1, 2] };
fn(obj.a);
obj.a = [1, 2, 3];

All 6 comments

b's type is inferred to be number[], not [number, number].

You can use the new as const assertion ([1, 2] as const) if you want b's type to be inferred differently.

@RyanCavanaugh but it works like that:

// from TS docs:
let x: [string, number];
// Initialize it
x = ["hello", 10]; // OK

Why can't I do like described above? It's the same.

I assume there are no plans to automatically "cast down" arrays to tuples in obvious cases like this? I've come across this many times before and it left me frustrated, this was before as const though so maybe that is a good compromise.

EDIT: maybe a suggestion in the error message would help, for people that don't know what's happening here it seems like the type system is broken.

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot

let x : [number, number] = [1, 2];
let y: number[] = [1,2];
x instanceof Array; // true
y instanceof Array; // true
x.length; // 2
y.length; // 2 
x = y; // Type 'number[]' is missing the following properties from type '[number, number]': 0, 1ts(2739)

Working as Intended

Rly? Ok.

Yes. Variables in TypeScript have the same read type as write type. This is an intentional decision that makes things more predictable.

Consider if this were allowed - this example illegally prints 3 instead of 2

function fn(x: { a: [number, number] }) {
  setTimeout(() => console.log(x.length);
}
const obj = { a: [1, 2] };
fn(obj.a);
obj.a = [1, 2, 3];
Was this page helpful?
0 / 5 - 0 ratings