- Notifications
You must be signed in to change notification settings - Fork 13.2k
Description
Search Terms
tuple, type, length
Suggestion
I'd like to see a way to specify the length of a tuple or array type when declaring it. For short tuples, it may be viable to write them out by hand like [number, number], but whenever the length is longer (say 10+), it becomes a chore.
Using the following approach to define a fixed-length tuple
// @ts-ignore interface can only extend interface or classinterfaceFixedLengthArray<Textendsany[],Lextendsnumber>extendsT{length: L;}has a few drawbacks:
1.: we cannot extend T because its not an interface or class.
2.: when ignoring that error, tuple literals are not inferred as tuples but as arrays when assigning them:
typeFoo=FixedLengthArray<number[],5>;constfoo1: Foo=[1,2,3,4,5];// error: length is not compatible, number not assignable to 5constfoo2: Foo=[1,2,3,4,5]as[1,2,3,4,5];// works, but defeats the purpose of that fixed-lengthOn the other hand, when using manually-written tuples, this works:
typeBar=[number,number,number,number,number];constbar1: Bar=[1,2,3,4,5];// no errorUse Cases
- Declaring fixed-length tuples or arrays with a large number of items
- Creating a Range union (e.g.
0 | 1 | 2 | 3 | 4from the keys of such a type) without having to resort to recursive types (currently broken, see TSServer hangs when using recursive types on tuples and pressing "," #26155)
Examples
I'll leave the syntax up for discussion, and provide the length in the square brackets for now:
typeT1=number[3];// equals [number, number, number]typeK1=keyofT1;// 0 | 1 | 2typeT2=number[100];// equals [number, number, ..., number] (100 items total)typeK2=keyofT2;// 0 | 1 | ... | 99typeT3=any[0];// equals [ ], type annotation is somewhat obsolete heretypeK3=keyofT3;// neverThe basic rules for tuple assignability should apply, as if the types were written out by hand.
Related:
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)