I am seeking to create a tuple type with a fixed size N, allowing for functionality such as:
let tuple: Tuple<string, 2> = ["a","b"]
In this scenario, "number" represents the type T, and "2" denotes the size N. Subsequently, I aim to develop a mathematical Vector class that not only embodies the tuple but also integrates additional methods like vector addition:
class Vector<N extends number> implements Tuple<number, N> {...}
While exploring various solutions for implementing the tuple type, I encountered several challenges. The simplest approach I came across (referenced here) entailed utilizing an interface structured as follows:
interface Tuple<T, N extends number> extends ArrayLike<T> //or Array<T> {
0: T
length: N
}
However, this particular implementation permits access to elements at invalid indices without triggering compiler errors:
let tuple: Tuple<number, 2> = [1,2]
tuple[4] //Compiler does not flag the out-of-bounds index.
An alternative implementation, found here, utilizes recursive conditional types:
type Tuple<T, N extends number> = N extends N ? number extends N ? T[] : _TupleOf<T, N, []> : never;
type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? R : _TupleOf<T, N, [T, ...R]>;
While resolving the index issue, this method poses challenges when integrating into the Vector class due to it being a type union, resulting in the following error:
A class can only implement an object type or intersection of the object types with statically known members.ts(2422)
Is there any viable approach to define a tuple type as intended?
Additional query: Is it possible to implement the tuple type sans the array class's inherent methods? Eliminating unrelated methods like filter and sort, especially those impacting the tuple's size, would be advantageous. Using ArrayLike in place of Array could address this concern, while Omit is another potential workaround albeit involving manual specification of each undesired method.