TypeScript Arrays
last modified October 15, 2026
An array is an ordered collection of values stored under one name.
TypeScript arrays are JavaScript arrays with a type for their elements. The
type is written as T[] or Array<T>, where
T is the element type; both forms mean the same thing. The
compiler checks that only elements of this type are added, and it knows the
type of every element that is read.
Creating Arrays
Arrays are usually created with array literals in square brackets.
const numbers: number[] = [1, 2, 3, 4, 5]; const fruits: Array<string> = ["Apple", "Banana", "Cherry"]; const mixed: (string | number)[] = ["a", 1, "b", 2]; const inferred = [true, false, true]; const empty: string[] = []; console.log(numbers); console.log(fruits); console.log(mixed, inferred, empty.length);
The numbers array uses the shorthand syntax and
fruits the generic Array<string> syntax. An
array may hold several types when its element type is a union; the
parentheses in (string | number)[] are required. The type of
inferred is boolean[], inferred from the
values.
An empty array literal needs an annotation. Without it, TypeScript cannot know what the array will contain.
$ npx tsx creating_arrays.ts [ 1, 2, 3, 4, 5 ] [ 'Apple', 'Banana', 'Cherry' ] [ 'a', 1, 'b', 2 ] [ true, false, true ] 0
Accessing Array Elements
Elements are read by their index. The first element has index 0.
const numbers: number[] = [10, 20, 30, 40, 50]; console.log(numbers[0], numbers[2]); console.log(numbers.at(-1)); console.log(numbers.length); console.log(numbers[10]);
The at method also accepts negative indexes, which
count from the end. The length property returns the number of
elements. Reading an index that does not exist returns
undefined.
Note that the compiler types numbers[10] as
number, not number | undefined. The
noUncheckedIndexedAccess compiler option makes index access
include undefined, which forces a check before the value is
used.
$ npx tsx accessing_elements.ts 10 30 50 5 undefined
Modifying Array Elements
An element is changed by assigning a new value to its index. The value must have the element type.
const numbers: number[] = [1, 2, 3, 4, 5]; numbers[1] = 10; numbers[numbers.length - 1] *= 2; console.log(numbers); // numbers[0] = "one"; // Error: Type 'string' is not assignable to type 'number'
The array is declared with const, but its elements can
still be changed: const only prevents assigning a different
array to the variable. The second assignment doubles the last element. The
commented line would not compile.
$ npx tsx modifying_elements.ts [ 1, 10, 3, 4, 10 ]
Adding and Removing Elements
Several methods add and remove elements at the ends of an array or in the middle.
const numbers: number[] = [1, 2, 3, 4, 5]; numbers.push(6); console.log(numbers); const last = numbers.pop(); console.log(last, numbers); const first = numbers.shift(); console.log(first, numbers); numbers.unshift(0); console.log(numbers); const removed = numbers.splice(1, 2, 99); console.log(removed, numbers);
The push method adds elements to the end and
pop removes the last one. shift removes the first
element and unshift inserts at the beginning. The
splice method removes two elements starting at index 1, inserts
99 in their place, and returns the removed elements.
The type of last and first is
number | undefined, because the array might be empty. All these
methods change the original array.
$ npx tsx array_methods.ts [ 1, 2, 3, 4, 5, 6 ] 6 [ 1, 2, 3, 4, 5 ] 1 [ 2, 3, 4, 5 ] [ 0, 2, 3, 4, 5 ] [ 2, 3 ] [ 0, 99, 4, 5 ]
Searching Arrays
Arrays have methods to test for values and to find elements that match a condition.
type Product = { id: number; name: string; price: number };
const products: Product[] = [
{ id: 1, name: "Keyboard", price: 45 },
{ id: 2, name: "Mouse", price: 20 },
{ id: 3, name: "Monitor", price: 180 },
];
const ids = products.map(p => p.id);
console.log(ids.includes(2), ids.indexOf(3));
const cheap = products.find(p => p.price < 30);
console.log(cheap?.name);
const missing = products.find(p => p.price > 1000);
console.log(missing);
console.log(products.findIndex(p => p.name === "Monitor"));
console.log(products.some(p => p.price > 100), products.every(p => p.price > 10));
The includes method checks for a value and
indexOf returns its position or -1. find returns the
first element for which the callback returns true; its type is
Product | undefined, so optional chaining is used to read the
name. findIndex returns the index of that element.
some tests whether at least one element matches and
every whether all of them do.
$ npx tsx searching_arrays.ts true 2 Mouse undefined 2 true true
Transforming Arrays
The map, filter, and reduce
methods create new values from an array without changing it.
const prices: number[] = [12, 45, 7, 30, 99];
const withTax = prices.map(price => Math.round(price * 1.2));
const expensive = prices.filter(price => price > 20);
const total = prices.reduce((sum, price) => sum + price, 0);
const labels = prices.map((price, index) => `#${index + 1}: ${price} EUR`);
console.log(withTax);
console.log(expensive);
console.log(total);
console.log(labels);
console.log(prices);
The map method applies a function to every element
and returns an array of the results; its element type can differ from the
original, as in labels, which is a string[].
filter keeps only the elements for which the callback returns
true. reduce combines all elements into one value;
the second argument, 0, is the initial value of sum.
The last line shows that the original prices array is
unchanged.
$ npx tsx transforming_arrays.ts [ 14, 54, 8, 36, 119 ] [ 45, 30, 99 ] 193 [ '#1: 12 EUR', '#2: 45 EUR', '#3: 7 EUR', '#4: 30 EUR', '#5: 99 EUR' ] [ 12, 45, 7, 30, 99 ]
Sorting Arrays
The sort method orders the elements of an array. Its
default behavior is a common trap with numbers.
const numbers: number[] = [10, 1, 5, 100, 25]; console.log([...numbers].sort()); console.log([...numbers].sort((a, b) => a - b)); console.log(numbers.toSorted((a, b) => b - a)); const words = ["pear", "Apple", "banana"]; console.log(words.toSorted((a, b) => a.localeCompare(b)));
Without a compare function, sort converts elements to
strings and compares them as text, so 100 comes before
25. A compare function that returns a negative number, zero, or a
positive number sorts numbers correctly; b - a sorts them in
descending order.
The sort method changes the array it is called on,
which is why the first two lines sort a copy made with the spread operator.
The newer toSorted method returns a sorted copy and leaves the
original untouched. It is part of ES2023, so the compiler needs
"target": "es2023" or a later target (or the matching
lib setting) in tsconfig.json. Strings are best sorted with
localeCompare.
$ npx tsx sorting_arrays.ts [ 1, 10, 100, 25, 5 ] [ 1, 5, 10, 25, 100 ] [ 100, 25, 10, 5, 1 ] [ 'Apple', 'banana', 'pear' ]
Iterating Over Arrays
Arrays can be traversed with the for...of loop, the
forEach method, or a classic for loop.
const fruits: string[] = ["Apple", "Banana", "Cherry"];
for (const fruit of fruits) {
console.log(fruit);
}
fruits.forEach((fruit, index) => {
console.log(`${index}: ${fruit}`);
});
for (const [index, fruit] of fruits.entries()) {
console.log(`${index + 1}. ${fruit.toUpperCase()}`);
}
The for...of loop is the simplest way to visit every
element. forEach also passes the index to its callback. The
entries method yields [index, element] pairs, which
the loop destructures; TypeScript infers index as
number and fruit as string.
$ npx tsx iterating_arrays.ts Apple Banana Cherry 0: Apple 1: Banana 2: Cherry 1. APPLE 2. BANANA 3. CHERRY
Readonly Arrays
A readonly array type, or
ReadonlyArray<T>, does not allow any changes.
function sum(values: readonly number[]): number {
values.push(0);
return values.reduce((acc, v) => acc + v, 0);
}
A function that takes a readonly array promises not to
modify it, and the compiler enforces the promise: methods such as
push, pop, and sort do not exist on
the type, and index assignment is rejected. Non-modifying methods such as
map, filter, and toSorted remain
available.
$ npx tsc --noEmit readonly_arrays.ts(2,12): error TS2339: Property 'push' does not exist on type 'readonly number[]'.
Multidimensional Arrays
An array of arrays represents a table or a grid. Its type is written with two pairs of brackets.
const matrix: number[][] = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
console.log(matrix[1][2]);
for (const row of matrix) {
console.log(row.join(" "));
}
const transposed = matrix[0].map((_, col) => matrix.map(row => row[col]));
console.log(transposed);
console.log(matrix.flat().reduce((sum, n) => sum + n, 0));
The expression matrix[1][2] selects the second row and
then its third element. The loop prints each row as a line of text.
The transposition turns rows into columns: for each column index, it
collects that element from every row. The flat method creates a
one-dimensional number[] from the matrix, here used to add up all
nine numbers.
$ npx tsx multidimensional_arrays.ts 6 1 2 3 4 5 6 7 8 9 [ [ 1, 4, 7 ], [ 2, 5, 8 ], [ 3, 6, 9 ] ] 45
Best Practices
- Type Empty Arrays: Annotate arrays that start empty; let the compiler infer the type of arrays initialized with values.
- Prefer Non-Mutating Methods: Use
map,filter,toSorted, and the spread operator when the original array must stay unchanged. - Always Pass a Compare Function to sort: The default sort compares elements as strings.
- Handle undefined from find: Methods such as
findandpopmay returnundefined; check the result. - Use readonly Parameters: Declare array parameters as
readonlywhen a function does not modify them.
Source
This tutorial covered arrays in TypeScript. The element type written in the array type is checked on every access, every added element, and every callback of the array methods.
Author
List all TypeScript tutorials.