Arrays, Tuples & Readonly Arrays
An array ( T[] or Array<T> ) holds many values of one type, a tuple ( [string, number] ) is a fixed-length list with a type per position, and readonly versions prevent mutation.
Learn Arrays, Tuples & Readonly Arrays in our free TypeScript course — an interactive lesson with runnable examples, a practice exercise and a quick reference.
Part of the free TypeScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn
💡 Real-World Analogy
An array is a shopping list — any number of items, all "things to buy". A tuple is a form field row : slot 1 is always the name, slot 2 always the age, in that exact order and never longer. A readonly array is a laminated reference card — you can read it all day, but you can't scribble new entries on it; to change anything you print a fresh card.
1. Arrays: T[] vs Array<T>
An array holds any number of values of a single type. You can write the type as number[] or as the generic Array<number> — they're identical . The payoff is that array methods preserve the element type: map over a number[] gives a number[] , and trying to push a value of the wrong type is a compile error.
2. Tuples & Named Members
A tuple is a fixed-length array where each position has its own type: [string, number] means "a string then a number, exactly two elements". Named tuple members ( [x: number, y: number] ) attach labels purely for readability — they don't change the runtime value. Tuples are ideal for fixed pairs and for returning several related values from one function.
3. Readonly Arrays/Tuples & Rest Elements
Prefix with readonly to forbid mutation: readonly number[] (or ReadonlyArray<number> ) removes push , pop , and index assignment at the type level, so you build a new array instead of changing the old one. A rest element in a tuple — [command: string, ...flags: string[]] — gives a fixed start followed by a flexible, typed tail.
🎯 Your Turn
Write labelled , which reads a [label, value] tuple. Fill in the two blanks marked ___ , then run it.
Common Errors (and the fix)
- ❌ "Type 'string' is not assignable to type 'number'" on push — wrong element type for the array. ✅ Push a value of the array's element type, or widen the type to a union.
- ❌ "Source has 3 element(s) but target allows only 2" — a tuple has a fixed length. ✅ Match the exact number of elements the tuple type declares.
- ❌ Tuple elements in the wrong order — [36, "Ada"] for [string, number] . ✅ Put each value in the position its type expects.
- ❌ "Property 'push' does not exist on type 'readonly ...'" — you tried to mutate a readonly array. ✅ Build a new array with the spread operator instead.
Pro Tips
- 💡 Pick one array syntax ( T[] is most common) and use it consistently across your codebase.
- 💡 Reach for a tuple whenever order and slot-meaning are fixed — it documents intent far better than a loose array.
- 💡 Name tuple members in shared types so editors show x and y instead of [0] and [1] .
- 💡 Default to readonly for data you don't intend to change — it makes accidental mutation a compile error.
Frequently Asked Questions
Mini-Challenge: Point Toolkit
No blanks this time — just a brief and a starting outline. Build the tuple-based point helpers yourself, run it, and check your output against the example in the comments.
🎉 Lesson Complete
- ✅ T[] and Array<T> are identical ways to type a list of one type
- ✅ Array methods ( map , filter ) preserve the element type
- ✅ A tuple is fixed-length with a type per position; order matters
- ✅ Named tuple members add labels for readability only
- ✅ readonly arrays/tuples block mutation at compile time; rebuild with spread
- ✅ Rest elements give a tuple a fixed start and a flexible typed tail
- ✅ Next lesson: Checkpoint — consolidate the whole type system
Practice quiz
How are number[] and Array<number> related?
- They are completely different types
- Array<number> allows mixed types
- They are exactly the same type, two syntaxes
Answer: They are exactly the same type, two syntaxes. number[] and Array<number> are identical - just two ways to write the same array type. Pick one and stay consistent.
What does the tuple type [string, number] describe?
- Exactly two elements: a string then a number
- An array of strings and numbers in any order
- An object with string and number keys
- A union of string and number
Answer: Exactly two elements: a string then a number. A tuple is a fixed-length array with a type per position: index 0 must be a string, index 1 must be a number.
When you map over a number[], what is the type of the result?
Array methods preserve the element type, so mapping a number[] gives a number[] (assuming the callback returns numbers).
What do named tuple members like [x: number, y: number] add?
- Runtime property names on the array
- Labels for readability only - no runtime change
- Automatic validation of values
- A conversion to an object
Answer: Labels for readability only - no runtime change. Named tuple members attach labels purely for readability and editor hints; they don't change the runtime value at all.
What does readonly do to an array at the type level?
- Removes mutating methods like push and index assignment
- Freezes the array at runtime
- Makes every element a string
- Limits the array to three elements
Answer: Removes mutating methods like push and index assignment. readonly removes push, pop, splice, and index assignment at the type level - a compile-time guarantee. The runtime array is still mutable.
How should you change a readonly number[] to add an element?
- Call .push() - it works on readonly arrays
- Cast it to any first
- Build a new array with the spread operator
- Use the delete keyword
Answer: Build a new array with the spread operator. You can't mutate a readonly array; build a new one instead, e.g. const bigger = [...a, 4].
What does a rest element in a tuple like [command: string, ...flags: string[]] mean?
- Exactly two strings
- A fixed leading string then any number of trailing strings
- An array that can never grow
- A tuple of unknown length only
Answer: A fixed leading string then any number of trailing strings. A rest element gives a fixed, typed start followed by a flexible typed tail - here one string then any number of string flags.
Why would you use a tuple instead of a plain array?
- When you have any number of same-typed items
- Tuples are always faster at runtime
- Arrays cannot hold objects
- When the length is fixed and each position has a specific meaning
Answer: When the length is fixed and each position has a specific meaning. Use a tuple when length is fixed and each slot means something (like [x, y]); use an array for any number of same-typed items.
For a tuple typed [string, number], why does [36, "Ada"] cause an error?
- Tuples can't hold numbers
- The element types are in the wrong order
- Tuples must have at least three elements
- Numbers must come last in every tuple
Answer: The element types are in the wrong order. Order matters in a tuple: position 0 must be a string and position 1 a number, so the values must line up with their declared types.
Which type is identical to readonly number[]?
- Array<number>
readonly number[] and ReadonlyArray<number> are two spellings of the same read-only array type.
Continue this course
- Previous: Function Overloads & this Types
- Next: Checkpoint: The Type System