Last updated: Feb 27, 2024
Reading time·5 min
Use a tuple to declare a fixed-length array in TypeScript.
Tuple types allow us to declare an array with a fixed number of elements whose types are known but can be different.
// ✅ Declare a fixed-length array let arr: [string, number, number]; arr = ['coords', 10, 5]; // ⛔️ Error: Type '[string]' is not // assignable to type '[string, number, number]'. arr = ['a'];
If you need to create an array of N empty elements, use the Array()
constructor instead.
const arr = new Array(4); console.log(arr); // 👉️ [, , ,] console.log(arr.length); // 👉️ 4
We declared a
tuple
with 3
elements with types of string
, number
and number
.
const arr: [string, number, number] = ['coords', 10, 5];
arr
variable to an array that doesn't contain 3
elements, you'll get an error.If you add the correct number of elements to the array but mix up the types, you'd also get an error.
let arr: [string, number, number]; arr = ['coords', 10, 5]; // ⛔️ Error: Type 'string' is not // assignable to type 'number'.ts(2322) arr = ['a', 10, 'b'];
The tuple type is used to declare an array with a fixed number of elements whose types are known but can be different.
Having said that tuples are represented by an array, and you are still able to
call the push()
method to add an element to the tuple.
const arr: [string, number, number] = ['coords', 10, 5]; // ✅ Ok arr.push('bobbyhadz.com'); // 👇️ [ 'coords', 10, 5, 'bobbyhadz.com' ] console.log(arr);
If you want to prevent this from happening, you can declare the tuple as
readonly
.
const arr: readonly [string, number, number] = ['coords', 10, 5]; // ⛔️ Error: Property 'push' does not exist // on type 'readonly [string, number, number]'.ts(2339) arr.push('bobbyhadz.com');
But this also means that you aren't able to change the values of the tuple's elements.
const arr: readonly [string, number, number] = ['coords', 10, 5]; // ⛔️ Cannot assign to '0' because // it is a read-only property.ts(2540) arr[0] = 'bobbyhadz.com'
Tuples are useful because when accessing a tuple at an existing index, TypeScript knows the type of the value.
const arr: [string, number, number] = ['coords', 10, 5]; console.log(arr[0].toUpperCase()); // 👉️ "COORDS" console.log(arr[1].toFixed(2)); // 👉️ "10.00"
If you try to access the tuple at an index that doesn't exist, the type checker would throw an error.
const arr: [string, number, number] = ['coords', 10, 5]; // ⛔️ Tuple type '[string, number, number]' of // length '3' has no element at index '3'.ts(2493) console.log(arr[3]);
If you need to declare an array that has a max length of X, use a tuple with optional values.
// ✅ Array of Max length let arrOfMaxLength3: [string?, string?, string?] = []; arrOfMaxLength3 = ['a', 'b', 'c']; // ✅ OK arrOfMaxLength3 = ['a', 'b']; // ✅ OK arrOfMaxLength3 = ['a']; // ✅ OK // ⛔️ Error: Source has 4 element(s) but target allows only 3. arrOfMaxLength3 = ['a', 'b', 'c', 'd'];
The question mark is used to mark the values in the tuple as optional. The tuple
in the example can have a maximum of 3
elements (unless you use array methods
to add more).
If you need to declare an array that has a minimum length of N, use the following approach.
let arrOfMin2: [string, string, ...string[]] = ['a', 'b']; arrOfMin2 = ['c', 'd'] // ✅ OK // ⛔️ Error: Source has 1 element(s) // but target requires 2.ts(2322) arrOfMin2 = ['c']
The array can have a minimum of 2
elements of type string
(unless you use an
array method to remove an element).
Use rest elements in a tuple type to declare a non-empty array.
let arr: [number, ...number[]] = [1]; // ⛔️ Error arr = [];
Alternatively, you can use a type alias with a generic.
type NonEmptyArr<T> = [T, ...T[]]; let arr: NonEmptyArr<string> = ['a']; arr = ['a', 'b']; // ✅ Works // ⛔️ Error arr = [];
We declared a non-empty array by using a
tuple,
that has a minimum length of 1
.
The first example shows how to declare a non-empty array where the first element
is a number
and may contain zero or more additional elements.
The ...number[]
syntax is called
Rest elements in tuple types
and indicates that the tuple is open-ended and may have zero or more additional
elements of the specified type.
[string, ...boolean[]]
means a tuple with a string
first element followed by any number of boolean
elements.The tuple can have more than 1 element, but if you try to re-declare it as an empty array, you'd get an error.
let arr: [number, ...number[]] = [1]; // ⛔️ Error: Source has 0 element(s) but target requires 1.ts(2322) arr = [];
The tuple type is used to declare an array with a fixed number of elements whose types are known but can be different.
You can also use a type alias to type a non-empty array.
type NonEmptyArr<T> = [T, ...T[]]; let arr: NonEmptyArr<string> = ['bobby']; arr = ['hadz', 'com']; // ✅ Works // ⛔️ Error arr = [];
The NonEmptyArr
type is an array that contains at least 1
element of type
T
, but may have zero or more additional elements of type T
.
Using this type alias in conditionals might be confusing.
type NonEmptyArr<T> = [T, ...T[]]; const arr: string[] = ['a']; function getArr(arr: NonEmptyArr<string>) { return arr; } if (arr.length > 0) { // ⛔️ Error: Argument of type 'string[]' is not // assignable to parameter of type 'NonEmptyArr<string>'. getArr(arr); }
The easiest way to get around this is to use a type assertion.
type NonEmptyArr<T> = [T, ...T[]]; const arr: string[] = ['a']; function getArr(arr: NonEmptyArr<string>) { return arr; } if (arr.length > 0) { // ✅ Works getArr(arr as NonEmptyArr<string>); }
Having said that tuples are represented by an array, and you are still able to
call the pop()
method to remove elements from the tuple.
const arr: [number, ...number[]] = [1]; arr.pop(); // ✅ OK console.log(arr); // 👉️ []
If you want to prevent this from happening, you can declare the tuple as
readonly
.
const arr: readonly [number, ...number[]] = [1]; // ⛔️ Error: Property 'pop' does not // exist on type 'readonly [number, ...number[]]'.ts(2339) arr.pop();
But this also means that you aren't able to change the values of the tuple's elements or add more elements.
I've also written an article on how to get the type of the array elements from an array type.