Array vs Tuple in TypeScript
TLDR: The type of an Array's length is
number
whereas a tuple's length is a finite static number.
So I was solving this typescript challenge isTuple the other day and I failed because I didn't know the key distinctions between a tuple and an array. So here I am sharing what I learned.
Arrays
Arrays are a list of values. These values can be of the same type or different types. It depends on the definition. One key feature of Arrays is that they have variable length. Values can be added/removed to it and the typescript won't complain about it.
// Array
let array: number[] = [1, 2, 3]
// Typescript won't complain if you update the array
array = [1, 2, 3, 4, 5] // Typescript - 🙂
array = [1] // // Typescript - 🙂
Note: Typescript will only complain if you add or remove items from the array which are different from the definition.
array = ['Hi, I am string', 2, 3]
// Typescript - 😡,
// Strings can't be added to the above array,
// as by the above defintion it only allows numbers
Tuples
Tuples are nothing but arrays with a fixed length.
// Tuples
let tuple: [number, number] = [1, 2]
tuple = [3, 4] // Typescript - 🙂
tuple = [1] // Typescript - 😡, Typescript expects two values
Length
The length
property of tuple and array will give you different results and is the key differentiator between array and the tuple in typescript.
Array's length
will give you the number
type
type ArrayOfNumbers = numbers[]
type LengthArray = ArrayOfNumbers['length']
// number
where Tuple's length will give you a finite number based on the definition
type TupleOfTwoNum = [number, number]
type LengthTuple = TupleOfTwoNum['length']
// 2
Note: A finite number like 2
is a subset of the number
type. But it does not work the other way around.
The number is not a subset of 2
type Example1 = 2 extends number ? true : false // true
type Example2 = number extends 2 ? true : false // false
IsTuple
Typescript Challenge
The above information on the length is the main thing you will need to solve the IsTuple
challenge.
Here is the solution as explained by the great Mike Poteat here:
type IsTuple<T> =
[T] extends [never]
? false
: T extends readonly unknown[]
? number extends T['length']
? false
: true
: false
Explaination:
[T] extends [never]
- checks if T isnever
T extends readonly unknown[]
- checks ifT
is an array or tuple.number extends T['length']
- checks ifT['length']
isnumber
, if it's a number, it means is an array, otherwise a tuple