Suppose you want to store the test scores of everyone in your class. With what you know so far you
might reach for a separate variable for each pupil: score1, score2,
score3… For thirty pupils that's thirty names to invent, thirty lines to type, and no
easy way to say "add them all up". It doesn't scale.
The fix is one of the most useful ideas in all of programming: an array (also
called a list). An array stores many values under a single name —
think of a row of numbered pigeonholes, or a train of carriages, all sharing one label. Instead of
thirty variables you have one, called scores, holding all thirty values in
order:
The square brackets [ ] make an array; the values inside, separated by commas, are its
elements. This one array does the job of five separate variables — and the same
idea works just as well for five thousand.
Each element has a numbered position called its index, and you fetch an element by
writing the array's name followed by the index in square brackets: scores[2]. There is
one thing that surprises everyone at first — the counting starts at zero. The first
element is at index
The little property .length tells you how many elements an array holds. Run this and
watch how the indices line up:
Notice the tidy trick in the last line: because the length is length - 1. That's why scores[scores.length - 1] is the universal way to
grab the final element, whatever the array's size.
The real power appears when you combine an array with a
i run from length, and on each pass scores[i] is the next element. One little loop
visits every item, no matter how many there are:
Read the condition carefully: i < scores.length, using <, not
<=. Because the indices run length - 1,
stopping before length is exactly right — it visits each element once and no
more. (Getting that comparison wrong is such a common slip that it has its own warning further down.)
Looping lets you process every element to work out a single answer about the whole
collection. Keep a running total as you go (an accumulator, just like summing
Finding the highest score is a lovely pattern. Start by assuming the first element is the biggest, then walk through the rest; whenever you meet something larger, remember it instead. By the end, your "biggest so far" really is the biggest:
The same shape (with the comparison flipped to <) finds the lowest. This
"carry the best-so-far through a loop" idea shows up everywhere once you start looking.
Loops and arrays also answer questions like "how many passed?" Keep a counter, and add one every
time an element meets your condition. Here the pass mark is
An array can hold text (strings) just as happily as numbers — a shopping list, say. And an
array isn't frozen at the size you first gave it: .push(value) adds a new
element to the end, and .length grows to match. Watch the list get longer:
See how the printed list numbers items i + 1, even though the computer stores them at indices
It looks like a nuisance, but there's a neat reason. Deep down, an array lives in a run of memory
slots one after another, and the index is really "how far from the start". The
very first element is the start, so it's zero steps along — index
The classic array mistake is running off the end. An array of length
length - 1, not length. Asking for
scores[5] doesn't crash in TypeScript; it quietly hands back
undefined, which then poisons any sum or comparison it touches:
The same trap hides in loops. Writing i <= scores.length (with
<=) makes the counter reach scores[5]. The safe habit is always
i < scores.length with a strict <, and to reach the
last element by scores[scores.length - 1]. Off-by-one at the end of an array
is one of the most common bugs there is — check it first.