Indexes start at 0
Every element of an array has a numbered position, its index. Indexing in TypeScript is zero-based: the first element has index 0, the second index 1, and so on. An array with n elements has the indexes 0 to n - 1, so the last element is at index length - 1.
You read an element with bracket notation: the name of the array, then the index in square brackets.
let myArray = ["Hello world!", 32, false];
console.log(myArray[0]);
console.log(myArray[1]);
console.log(myArray[2]);
Hello world!
32
false
Printing a string with console.log shows it without quotes. Printed inside an array, the same string appears quoted.
Using elements in expressions
An element read with array[i] is a value of the element type, so it works anywhere such a value would. If ages is a number[], then ages[0] is a number and can be added or subtracted. The index itself can be any expression that produces a number, such as ages.length - 1, which is the last index:
let ages: number[] = [14, 32, 50, 21];
console.log(ages[ages.length - 1]);
console.log(ages.at(-1));
21
21
The method at accepts a negative index and counts from the end, so at(-1) is the last element. The bracket form has no such feature, as the next section shows.
Variables as indexes and elements of elements
The index can be held in a variable. This is what makes arrays powerful: one expression, ages[i], reaches a different element as i changes. A loop that walks every valid index prints each position and value:
let ages: number[] = [14, 32, 50, 21];
for (let i = 0; i < ages.length; i++) {
console.log(i, ages[i]);
}
0 14
1 32
2 50
3 21
The loop condition is i < ages.length, not i <= ages.length, because the last valid index is one less than the length.
An element can also be used further. The elements of fruits are strings, so fruits[2].length is the length of "grapefruit", which is 10, and fruits[1].toUpperCase() is "KIWI". Indexing works on a string too: fruits[0][0] is "m", the first character of "mango".
Gotchas
- Off-by-one. The second element is at index 1, not 2, and the last element of a four-element array is at index 3, not 4.
- Out of range gives
undefined, not an error. Reading past the end, or at a negative index, returnsundefined:let ages: number[] = [14, 32, 50, 21]; console.log(ages[10], ages[-1], ages[4]);undefined undefined undefined - The type does not warn you. The type of
ages[10]isnumber, solet n: number = ages[10];compiles. Types are erased at run time, and the value is reallyundefined. Doing arithmetic with it givesNaN:n + 1printsNaN. When an index might be out of range, check it againstlengthfirst. - Indexes are numbers.
ages[1]reads the element at 1. Writingages[1.5]givesundefined, because there is no element at that position.
The lesson's exercise
The starting code has two arrays: fruits, a string[] holding "mango", "kiwi" and "grapefruit", and ages, a number[] holding 14, 32, 50 and 21. The task is to print three values.
- The second fruit. The second item is at index 1, so print
fruits[1]. This printskiwi. - The sum of the first three ages. Index each of them and add them inside
console.log:ages[0] + ages[1] + ages[2]. The expression is evaluated first and the call receives the finished sum, 14 + 32 + 50, which is96. - The last age minus the first. There are four ages, so the last is at index 3. Print
ages[3] - ages[0], which is 21 - 14, or7.
let fruits: string[] = ["mango", "kiwi", "grapefruit"];
let ages: number[] = [14, 32, 50, 21];
console.log(fruits[1]);
console.log(ages[0] + ages[1] + ages[2]);
console.log(ages[3] - ages[0]);
The output is:
kiwi
96
7
Notice the difference between adding numbers and joining strings. The elements of ages are numbers, so + adds them. If the elements were strings, the same expression would glue them together.
Key takeaways
- Indexes start at 0, and the last valid index is
length - 1. - Read an element with
array[index]. The result has the array's element type. - An index outside the array gives
undefined, with no error and no compiler warning. - Use
at(-1)to read from the end, sincearray[-1]isundefined.