RizTech Academy logo
RizTech Academy
The Basic TypesLesson 2 of 620 min

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

  1. Declare a number[] and a string[]. Push a valid value and an invalid one; read the error.
  2. Write the same array type as Array<T> and confirm it is identical.
  3. Declare (string | number)[] and string[] | number[] and put values in each. Explain why one accepts a mixed array and the other does not.
  4. Make a readonly number[] and try to push and to reassign an element. Read both errors.
  5. Write a function taking a readonly number[] and confirm callers cannot rely on it mutating.
  6. Declare a [string, number] tuple. Try the wrong order and the wrong length; read both errors.
  7. Access element 0 and 1 of the tuple and confirm each has the right type.
  8. Label a [latitude: number, longitude: number] tuple and note the editor hints. Decide when you would use an object instead.

Official documentation

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