Lists are everywhere, and tuples are how TypeScript types functions that return several values, like React's useState.
An array type is written T[] or Array<T> — both mean the same thing. Mixed arrays use a union in parentheses: (string | number)[]. Array methods are fully typed, so nums.map(n => n.toFixed(1)) returns string[].
A tuple is an array with a fixed length and a known type at each position: [string, number]. Tuples are perfect for small, positional results — a key/value pair, a coordinate, or a function returning two things:
function useCounter(): [number, () => void] { /* ... */ }
const [count, increment] = useCounter();Tuples can have labels for documentation ([x: number, y: number]), optional elements ([string, number?]) and rest elements ([string, ...number[]]).
Note that an array literal is inferred as an array, not a tuple: const p = [1, "a"] is (string | number)[]. Annotate the tuple type, or use as const (covered later) to get one.
`readonly` arrays (readonly string[] or ReadonlyArray<string>) remove mutating methods like push and sort. Use them for parameters you don't intend to change; callers can still pass ordinary arrays. The reverse is not allowed — a readonly array can't be passed where a mutable one is expected.
One important hole: by default, indexing arr[10] is typed as the element type even if the array is shorter, so the result could really be undefined. The noUncheckedIndexedAccess option (see the strict-options lesson) makes such reads T | undefined.
Example
const scores: number[] = [90, 72, 85];
const labels: Array<string> = scores.map(s => `${s}%`);
// A tuple: fixed positions with known types
type Entry = [key: string, value: number];
const entry: Entry = ["apples", 3];
const [fruit, qty] = entry; // fruit: string, qty: number
// Optional and rest elements
type Log = [message: string, ...details: unknown[]];
const log: Log = ["saved", { id: 1 }, 42];
function total(values: readonly number[]): number {
// @ts-expect-error -- push does not exist on readonly number[]
values.push(0);
return values.reduce((a, b) => a + b, 0);
}
console.log(labels, fruit, qty, log.length, total(scores));Remember
T[]andArray<T>are the same type- Tuples type fixed-length positional data:
[string, number] - Take
readonly T[]parameters when you don't mutate the input
Watch out for
- Expecting
const pair = [1, "a"]to be a tuple — it's inferred as(string | number)[].