Arrays, Tuples, and Readonly in TypeScript In Depth
Arrays, Tuples, and Readonly In Depth
~13 Min. Lesezeit Zuletzt aktualisiert am August 8, 2026
To wrap up Phase 2, let's explore arrays and tuples from chapter 4 further – including readonly arrays, named tuple elements, and optional tuple positions.
readonly arrays: protection against accidental mutation
function showGenres(genres: readonly string[]): void {
console.log(genres.join(', '));
genres.push('New'); // error - push() mutates the array, readonly forbids that
}
const allGenres: readonly string[] = ['Fantasy', 'Mystery'];
allGenres[0] = 'Novel'; // error - direct index assignment is forbidden tooEXACTLY like readonly on interface properties (chapter 7), readonly string[] prevents the array from being mutated AFTER being passed – useful as a "contract" when a function should only READ an array, never modify it.
An important difference: readonly array vs. const array
const genres: string[] = ['Fantasy'];
genres.push('Mystery'); // ✓ ALLOWED - const only prevents REASSIGNING the variable,
// NOT modifying the array's CONTENTS
genres = ['Novel']; // ✗ error - THAT'S what const forbidsAchtung: A common misconception: const does NOT make an array immutable – it only prevents the VARIABLE itself from being reassigned. push(), splice(), direct index assignment all remain allowed with const. For GENUINE immutability, you need readonly, as shown above.
Named tuple elements
type ShelfPosition = [shelf: string, slot: number, position: number];
function formatPosition(pos: ShelfPosition): string {
const [shelf, slot, position] = pos; // destructuring as usual
return `${shelf}, slot ${slot}, position ${position}`;
}The names shelf/slot/position in the type definition are pure DOCUMENTATION – they change NOTHING about the actual behavior (the tuple remains a normal array with three elements), but considerably improve readability, especially in autocompletion when hovering over the type.
Optional tuple elements
type SearchFilter = [query: string, genre?: string];
const filter1: SearchFilter = ['Tolkien'];
const filter2: SearchFilter = ['Tolkien', 'Fantasy'];
const filter3: SearchFilter = ['Tolkien', 'Fantasy', 'extra']; // error - too many elementsIn practice: organizing library data with typed arrays
import { Book } from '../models/Book.js';
import { Author } from '../models/Author.js';
export const tolkien: Author = {
name: 'J.R.R. Tolkien',
birthYear: 1892,
nationality: 'British',
};
export const orwell: Author = {
name: 'George Orwell',
birthYear: 1903,
nationality: 'British',
};
export const libraryStock: readonly Book[] = [
{
isbn: '978-0-618-64015-7',
title: 'The Lord of the Rings',
author: tolkien,
publicationYear: 1954,
pageCount: 1216,
genres: ['Fantasy'],
status: 'available',
},
{
isbn: '978-0-452-28423-4',
title: '1984',
author: orwell,
publicationYear: 1949,
pageCount: 328,
genres: ['NonFiction', 'Novel'],
status: 'borrowed',
},
];libraryStock: readonly Book[] – the ENTIRE library stock is deliberately modeled as a read-only array. That's intentional: ADDING or REMOVING books should later go through dedicated, controlled functions (chapter 13, classes), not through direct array manipulation from anywhere in the code.
Tipp: That wraps up Phase 2: interfaces, type aliases, union/intersection, literal types/enums, and now in-depth arrays/tuples. Starting next chapter, we turn to OBJECT-ORIENTED programming – classes, which bundle not just data but also BEHAVIOR.