Skip to content
Laviyx Learn

Try

TypeScript course menu

TypeScript Arrays and Tuples: string[], Array<T>, readonly Arrays and Tuple Types

Learn to type arrays in TypeScript with string[] and Array<string>, arrays of objects and unions, readonly arrays, tuples for fixed-length arrays with known positions, optional and named tuple elements, and when to use an object instead.

Beginner7 min readUpdated
On this page

Arrays are typed by the type of their items. Tuples are arrays with a fixed length where each position has its own type.

Array types#

There are two equivalent ways to write an array type:

TypeScript
const scores: number[] = [72, 95, 58];
const names: Array<string> = ["Asha", "Ravi"];

scores.push(88);
console.log(scores, names);
Output
[ 72, 95, 58, 88 ] [ 'Asha', 'Ravi' ]

number[] is the more common style. Array<number> uses generic syntax, explained in Generics.

Every item must match the type:

TypeScript
const scores: number[] = [72, 95];
scores.push("100");
Compiler error
error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.

Array methods know the item type, so their results are typed too:

TypeScript
const prices = [120, 450, 80];
const labels = prices.map((p) => `₹${p}`);       // string[]
const total = prices.reduce((sum, p) => sum + p, 0);   // number
console.log(labels, total);
Output
[ '₹120', '₹450', '₹80' ] 650

Arrays of objects and unions#

TypeScript
const students: { name: string; marks: number }[] = [
  { name: "Asha", marks: 92 },
  { name: "Ravi", marks: 78 },
];

const ids: (string | number)[] = [101, "A-7", 205];

console.log(students.filter((s) => s.marks > 80).map((s) => s.name));
console.log(ids.length);
Output
[ 'Asha' ]
3

Note the parentheses in (string | number)[]: an array whose items are strings or numbers. Without them, string | number[] would mean "a string, or an array of numbers". Object types are usually given a name with an interface or type alias.

Reading items#

By default, TypeScript assumes an index you read exists, so scores[10] has the type number, even though at runtime it is undefined. The noUncheckedIndexedAccess compiler option makes indexed reads include undefined, forcing you to check (tsconfig.json). Methods like find and at already return T | undefined:

TypeScript
const scores = [72, 95, 58];
const firstHigh = scores.find((s) => s > 90);   // number | undefined
console.log(firstHigh ?? "none");
Output
95

readonly arrays#

A readonly array cannot be changed, which is useful for function parameters that should not modify their input:

TypeScript
function total(prices: readonly number[]): number {
  prices.push(0);
  return prices.reduce((a, b) => a + b, 0);
}
Compiler error
error TS2339: Property 'push' does not exist on type 'readonly number[]'.

Non-mutating methods such as map, filter, slice and toSorted still work. ReadonlyArray<number> is the same type written generically.

Tuples#

A tuple is an array with a fixed number of items, where each position has a known type:

TypeScript
const point: [number, number] = [12, 7];
const entry: [string, number] = ["maths", 92];

const [subject, mark] = entry;
console.log(point[0] + point[1], subject.toUpperCase(), mark + 1);
Output
19 MATHS 93

Positions are checked:

TypeScript
const entry: [string, number] = [92, "maths"];
Compiler error
error TS2322: Type 'number' is not assignable to type 'string'.

Where tuples appear#

Functions that return several values often return tuples, which callers destructure. React's useState is a famous example. Object.entries returns [string, T][]:

TypeScript
function minMax(values: number[]): [number, number] {
  return [Math.min(...values), Math.max(...values)];
}

const [lowest, highest] = minMax([7, 3, 9, 4]);
console.log(lowest, highest);

for (const [key, value] of Object.entries({ tea: 20, coffee: 35 })) {
  console.log(key, value);
}
Output
3 9
tea 20
coffee 35

Named, optional and rest elements#

TypeScript
type Range = [start: number, end: number];          // names document each position
type Rgb = [red: number, green: number, blue: number, alpha?: number];
type Command = [name: string, ...args: string[]];   // rest elements

const r: Range = [1, 10];
const colour: Rgb = [47, 95, 224];
const cmd: Command = ["git", "commit", "-m", "Initial commit"];
console.log(r, colour.length, cmd.slice(1).join(" "));
Output
[ 1, 10 ] 3 commit -m Initial commit

(type creates a name for a type; see Type Aliases.)

Tuple or object?#

Tuples are compact but positions are easy to mix up. If there are more than two or three values, or their meaning is not obvious, use an object with named properties instead: { start: 1, end: 10 }.

Practice#

Practice exercise

Write a function splitName(full: string): [first: string, last: string] that splits a full name at the first space (the last name is the rest, or an empty string), and a function averageOf(values: readonly number[]): number. Test them.

Show solution
TypeScript
function splitName(full: string): [first: string, last: string] {
  const space = full.indexOf(" ");
  return space === -1 ? [full, ""] : [full.slice(0, space), full.slice(space + 1)];
}

function averageOf(values: readonly number[]): number {
  return values.length === 0 ? 0 : values.reduce((a, b) => a + b, 0) / values.length;
}

const [first, last] = splitName("Asha Devi Rao");
console.log(first, "|", last);
console.log(splitName("Meera"));
console.log(averageOf([70, 85, 90]).toFixed(1));
Output
Asha | Devi Rao
[ 'Meera', '' ]
81.7

Key takeaway#

Finished this lesson?