Lesson 10 · Module 1.5 — Core type vocabulary
There’s a sharp line worth drawing: string[] is a homogeneous, any-length
array, while [string, number] is a fixed-length, positional tuple. The same
square brackets, two very different contracts. Once you see it, advanced generics over function
parameters stop looking alien.
T[] — same type, any lengthtype Names = string[];
const names: Names = ["Alice", "Bob", "Charlie"]; // any number of strings
names[0]; // string
names[100]; // string (TS assumes the element type at every index)
Read string[] as “a list of strings — could be 0, 3, or 300 of them.” Every position
has the same type, and the length is open.
[A, B, C] — fixed length, type per positiontype PersonTuple = [string, number, boolean];
const person: PersonTuple = ["Alice", 25, true]; // exactly 3 elements
person[0]; // string
person[1]; // number
person[2]; // boolean
person[3]; // ERROR — the tuple only has 3 elements
Read [string, number, boolean] as “exactly three slots: a string, then a number, then
a boolean.” The order and the count are part of the type. That is the whole
distinction:
array T[] | tuple [A, B] | |
|---|---|---|
| length | variable / open | fixed |
| element types | all the same | one per position |
| position matters? | no | yes |
Here is the payoff this idea builds toward. A function’s parameters have different types at fixed positions in a fixed order — which is exactly a tuple. So when a generic captures “all the arguments,” it captures them as a tuple, not an array:
const updateUser = (id: number, name: string, email: string) => {};
// ❌ Array approach — loses type safety:
type ArrayApproach = (...args: any[]) => void; // can't tell positions apart, all info lost
// ✅ Tuple approach — preserves type safety:
type TupleApproach = (...args: [number, string, string]) => void;
// └ exact types at exact positions ┘
Read ...args: [number, string, string] as “the rest-spread of a tuple” — it’s just
(id: number, name: string, email: string) written as one positional type. This is why
library types you’ll meet later say ...args: TArgs with TArgs extends any[]:
TArgs is really a tuple of the parameter types, captured so each position keeps its own
type. An any[] would flatten them all to one type and throw the positions away.
Brackets with one element type and a trailing [] →
array (homogeneous, open length). Brackets listing several types
in order → tuple (positional, fixed length). A ...rest of a tuple is a
parameter list.
Recall, don’t re-read. (Answers reveal on click.)
string[] and [string] differ?person: [string, number, boolean], what does person[3] give?The handbook section is
Object Types — Tuple Types
(arrays are covered just above, under Array Types). Best way to feel it: paste the
PersonTuple block into the
TS Playground, then try adding a 4th element and
read the error.
See a [...] and unsure if it’s a tuple or an array? Check whether it lists one
element type with a trailing [], or several types in order. Next lesson
(1.6): the never type — its two faces in exhaustive switches and in mapped
types.