In this answer, we learn how to define tuples of length N
in typescript so that
TupleOf<string, 3>
is basically the same as the type [string, string, string]
.
Now I would like to use this in a class with a generic parameter N
like
class Dimension<N extends number> {
private data: TupleOf<number, N> = /* ?? what here ?? */;
}
yet I fail to come up with a type safe way to initialize the data property. It should be a length N
array of numbers, but I think this requires to convert the (trivial union) type N
to a value, which according to this answer this is not possible.
I could require any use site to provide an initial value to the constructor.
class Dimension<N extends number> {
private data: TupleOf<number, N>;
constructor(data: TupleOf<number, N>) {
this.data = data;
}
}
Yet in general there may be cases where this is cumbersome, so the question remains: is there a way to initialize the data without getting values into the constructor?
CodePudding user response:
[...] is there a way to initialize the data without getting values into the constructor?
Yes, this example does the trick.
class Dimension<N extends number> {
public readonly data: Tuple<number, N>
constructor(dataSize: N) {
this.data = this.getInitialData(dataSize)
}
private getInitialData(dataSize: N): Tuple<number, N> {
const data: number[] = Array(dataSize).fill(0)
return data as Tuple<number, N>
}
}
const d = new Dimension(5)
console.log(d.data) // [ 0, 0, 0, 0, 0 ]
There's one restriction, though:
With the N extends number
typescript knows about the tuple size, but at runtime these types don't exist. This means that in order to initialize the tuple inside the class, the size of the tuple has to be passed to the constructor.
However, there's no need to explicitly give both the type and the parameter (new Dimension<5>(5)
) because the generic is inferred.