Arrays and tuples
Almost every program holds collections of things — a list of prices, a set of names, a row of coordinates. TypeScript types these with arrays (any number of one type) and tuples (a fixed number of possibly-different types). Getting the notation and the difference right is a first-week skill.
Arrays
An array holds any number of values, all the same type. There are two ways to write the type, and they mean exactly the same thing:
const prices: number[] = [120, 340, 90]; // preferred
const names: Array<string> = ["Kavita", "Ravi"]; // identical meaning
number[] reads as "array of number". Array<string> is the generic form (the generics module
explains the <>). Prefer number[] — it is shorter and the community standard — and reserve
Array<...> for when the element type is complex enough that the postfix [] gets hard to read.
The array's type flows into everything you do with it:
const prices: number[] = [120, 340, 90];
prices.push(500); // fine — 500 is a number
prices.push("free"); // error: Argument of type 'string' is not assignable to 'number'
const first: number = prices[0]; // TypeScript knows elements are number
const doubled = prices.map(p => p * 2); // knows p is number, result is number[]
Every operation is checked: you cannot push the wrong type, and map/filter/reduce know the
element type without you saying so. This is inference working through a collection — the reason typed
array code is barely more verbose than untyped.
Arrays of object types, and of unions
The element type can be anything:
type Book = { title: string; price: number };
const books: Book[] = [{ title: "Sairat", price: 300 }];
const mixed: (string | number)[] = ["Pune", 411038, "Mumbai"]; // each element is string OR number
const ids: string[] | number[] = [1, 2, 3]; // the WHOLE array is one or the other
Watch the last two — the parentheses matter. (string | number)[] is an array where each element
may be a string or a number. string[] | number[] is a value that is either an all-string array
or an all-number array. Getting the brackets wrong is a common early mistake, and the difference is
real.
The readonly array — a collection nobody can mutate
Just as a value can be readonly, an array can be immutable — no push, no pop, no reassigning
elements:
const prices: readonly number[] = [120, 340, 90];
prices.push(500); // error: Property 'push' does not exist on type 'readonly number[]'
prices[0] = 999; // error: Index signature in type 'readonly number[]' only permits reading
A readonly number[] (also written ReadonlyArray<number>) has all the reading methods —
map, filter, indexing — but none that mutate. This is enormously useful for a function parameter:
declaring function report(prices: readonly number[]) tells every caller "I will not modify your
array", which is a promise the compiler enforces. The immutability lesson in the data-structures
module returns to this; the habit to plant now is prefer readonly for arrays you only read,
especially parameters.
Tuples — a fixed shape, possibly mixed types
An array is any number of one type. A tuple is a fixed number of values, each with its own type, in a fixed order:
let coord: [number, number] = [18.52, 73.85]; // exactly two numbers: latitude, longitude
let entry: [string, number] = ["Kavita", 33]; // a string then a number
[number, number] is a tuple of exactly two numbers. [string, number] is a string followed by a
number — different types, fixed positions. TypeScript enforces both the length and the type at each
position:
let entry: [string, number] = ["Kavita", 33];
entry = [33, "Kavita"]; // error: types are in the wrong positions
entry = ["Kavita"]; // error: Source has 1 element(s) but target requires 2
const name = entry[0]; // TypeScript knows this is a string
const age = entry[1]; // and this is a number
Tuples are what functions return when they hand back a small fixed set of values — the pattern React's
useState uses (const [value, setValue] = useState(0) returns a [state, setter] tuple). They are
also cleaner than an object when the values have an obvious order and no obvious names.
Labelled tuples, for readability
A bare [number, number] does not say which number is which. TypeScript lets you label tuple
elements — purely for documentation, it does not change the type:
type Coord = [latitude: number, longitude: number];
Now anyone reading Coord, and the editor's hints when you use it, tell you position 0 is latitude and
position 1 is longitude. Label your tuples when the positions are not obvious — it is a free
readability win. (When there are more than two or three values, or the order is not obvious, prefer an
object with named properties; a tuple is for a small, ordered, obvious set.)
Array versus tuple — choosing
- Array (
T[]) — you have some number of the same thing. A list of prices, a set of names, a collection of books. The count varies. - Tuple (
[A, B]) — you have a fixed number of things, possibly of different types, in a known order. A coordinate, a key-value pair, a function returning two related values.
If the count can grow, it is an array. If the count is fixed and the positions mean specific things,
it is a tuple. And whenever you only read a collection, reach for readonly.
Check your work
Two ways to write an array type. number[] (preferred) and Array<number> (identical).
How array types flow. push, indexing, and map/filter are all checked against the element
type, inferred automatically.
(string | number)[] versus string[] | number[]. Each element may be a string or number,
versus the whole array is one type or the other.
What a readonly array forbids. Mutating methods (push, pop) and element assignment — only
reading remains; ideal for parameters.
What a tuple is. A fixed number of values, each with its own type, in a fixed order.
What a tuple enforces. Both the length and the type at each position.
What labelled tuples add. Documentation of what each position means, with no change to the type.
Array versus tuple. Varying count of one type → array; fixed count of possibly-different types in a known order → tuple.
Practice
- Declare a
number[]and astring[]. Push a valid value and an invalid one; read the error. - Write the same array type as
Array<T>and confirm it is identical. - Declare
(string | number)[]andstring[] | number[]and put values in each. Explain why one accepts a mixed array and the other does not. - Make a
readonly number[]and try topushand to reassign an element. Read both errors. - Write a function taking a
readonly number[]and confirm callers cannot rely on it mutating. - Declare a
[string, number]tuple. Try the wrong order and the wrong length; read both errors. - Access element 0 and 1 of the tuple and confirm each has the right type.
- Label a
[latitude: number, longitude: number]tuple and note the editor hints. Decide when you would use an object instead.
Official documentation
- TypeScript — Everyday Types: arrays — The two notations.
- TypeScript — Tuple types — Fixed-length, per-position typing, and labels.
- TypeScript — ReadonlyArray — Immutable arrays.
Next: enums, and why a union of literals is usually better.
Stuck on this lesson?
Being stuck is part of it — but being stuck alone for three days is not. Our internship programme pairs this curriculum with code review and one-to-one help from working developers, and it is free.
About the internship