TypeScript Type Challenge Length of Tuple Walkthrough
The goal of the challenge is to implement a generic type called Length that takes an array and returns the length of that array.
The challenge: https://github.com/type-challenges/type-challenges/blob/main/questions/00018-easy-tuple-length/README.md
Watch the video
An example case
For example, given the following cases, our Length type should return the type shown in the comments:
Length<typeof tesla> // 4
Length<typeof spaceX> // 5
Length<5> // @ts-expect-error
Length<'hello world'> // @ts-expect-error
Approach
Like in the Tuple To Object, we're interested in the type of a specific element of an array. We can use indexed access types to do this.
We know that in TypeScript, like JavaScript arrays are objects, and those objects have a length
property signifying their length. We therefore know that the T["length"]
should give us the length of an array.
type Length<T> = T["length"]
The solution
The above works, but throws TypeScript errors, as TypeScript doesn't have a guarantee that the type T
passed into length will be an array, it may therefore not have a length
property.
To solve this we can constrain the type of T to be only arrays:
type Length<T extends any[]> = T["length"]
This solves most of our issues but leaves us with two errors in our example cases above. The errors occur as when we call Length<typeof tesla>
the typeof tesla
is a readonly array. We can't assign a readonly array to a any[]
type, we therefore need to further constrain T
to only allow readonly arrays.
type Length<T extends readonly any[]> = T["length"]
This readonly
constraint makes sense, as if we pass in a mutable array to Length
, the only type that we will be able to get back will be number
, rather than the length of our array. This is because mutable arrays can be changed at runtime, so TypeScript cannot infer the length of it.