Assume arity of tuples when declared as literal
See original GitHub issueSearch Terms
tuples, length, arity
Suggestion
Now that #17765 is out I’m curious about if we could change the arity of tuples declared as literals. This was proposed as part of #16896 but I thought it might be better to pull this part out to have a discussion about this part of that proposal.
With fixed length tuples TypeScript allows you to convert [number, number]
to number[]
but not the other way around (which is great).
const foo = [1, 2];
const bar = [1, 2] as [number, number];
const foo2: [number, number] = foo;
const bar2: number[] = bar;
If you declare a constant such as foo
above it would be nice if it would be nice if it would have the length as part of its type, that is, if foo
was assumed to be of type [number, number]
not number[]
.
This would have potential issues with mutable arrays allowing you to call push
and pop
although this isn’t different to present and was discussed a bit in #6229.
const foo = [1, 2] as [number, number]; // After this proposal TypeScript would infer the type as `[number, number]` not `number[]`.
foo.push(3); // foo is of type `[number, number]` even though it now has 3 elements.
foo.splice(2); // And now it has 2 elements again.
Use Cases
When using a function such as fromPairs
from lodash it requires that the type is a list of tuples. A simplified version is
function fromPairs<T>(values: [PropertyKey, T][]): { [key: string]: T } {
return values.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
}
If I do
const foo = fromPairs(Object.entries({ a: 1, b: 2 }));
it works because the type passed into fromPairs
is [string, number][]
, but if I try to say map the values to double their value I get a compile error:
const bar = fromPairs(Object.entries({ a: 1, b: 2 }).map(([key, value]) => [key, value * 2]));
as the parameter is of type (string | number)[][]
This can be fixed by going
const bar = fromPairs(Object.entries({ a: 1, b: 2 }).map(([key, value]) => [key, value * 2] as [string, number]));
but this is cumbersome.
Checklist
My suggestion meets these guidelines:
- This wouldn’t be a breaking change in existing TypeScript / JavaScript code
- This wouldn’t change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn’t a runtime feature (e.g. new expression-level syntax)
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:13 (3 by maintainers)
Top GitHub Comments
I WILL TURN THIS CAR AROUND
We did consider this when we were first adding support for tuples, and thought it was too big of a breaking change to add… there are a few issues already open proposing new syntax to address this: https://github.com/Microsoft/TypeScript/issues/16656 and https://github.com/Microsoft/TypeScript/issues/10195.
having said that, i would like to bring this back to discussion. i gave it a try today, and there were not that many breaks in our Real World Code, which is frankly surprising to me… they fall into two categories: