🔷 TypeScript Q36 / 101

What is readonly array?

AI-Powered Answer ✓ Answered

In TypeScript, a `ReadonlyArray` is a special type that ensures an array cannot be modified after its creation. It's a powerful tool for promoting immutability and preventing unintended side effects in your code.

What is a Readonly Array?

A ReadonlyArray<T> is a generic type that represents an array whose elements can be read, but whose structure or contents cannot be changed via methods that mutate the array. This means you cannot add, remove, or reorder elements, nor can you directly assign to an index.

It's important to distinguish ReadonlyArray<T> from a regular array type Array<T> or T[]. While a T[] allows all array operations (reading and mutating), a ReadonlyArray<T> only allows read-only operations.

typescript
const numbers: ReadonlyArray<number> = [1, 2, 3];
const names: readonly string[] = ["Alice", "Bob"]; // Shorthand syntax

// You can read elements
console.log(numbers[0]); // Output: 1
console.log(names.length); // Output: 2

Key Characteristics and Limitations

  • Immutability: Methods like push(), pop(), splice(), sort(), reverse(), etc., are not available on a ReadonlyArray.
  • Index Assignment: You cannot directly assign a new value to an index (e.g., arr[0] = 10; is disallowed).
  • Type Compatibility: A regular mutable array (T[]) can be assigned to a ReadonlyArray<T>. However, a ReadonlyArray<T> cannot be assigned directly to a T[] without a type assertion, as it would lose the immutability guarantee.
  • Shallow Immutability: The ReadonlyArray itself is immutable, but if its elements are objects, those objects can still be mutated if they are not also readonly or immutable types.
typescript
const colors: readonly string[] = ["red", "green", "blue"];

// colors.push("yellow"); // Error: Property 'push' does not exist on type 'readonly string[]'.
// colors[0] = "scarlet"; // Error: Index signature in type 'readonly string[]' only permits reading.

const mutableColors: string[] = ["orange", "purple"];
const readOnlyColors: readonly string[] = mutableColors; // Allowed

// mutableColors = readOnlyColors; // Error: The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'string[]'.

When to Use Readonly Arrays

  • Function Parameters: When a function receives an array and you want to guarantee that the function will not modify the original array, declare the parameter as ReadonlyArray<T>.
  • State Management: In patterns like Redux or React's state, using ReadonlyArray helps enforce that state arrays are never mutated directly, encouraging the creation of new arrays for state updates.
  • API Responses: If you receive an array of data from an API that should be treated as fixed and unchangeable, defining it as ReadonlyArray provides compile-time checks.
  • Data Structures: For any data structure that should remain constant after initialization.
typescript
function processData(data: ReadonlyArray<{ id: number; name: string }>): void {
  // data.push({ id: 3, name: "Charlie" }); // Error
  console.log("Processing", data.length, "items.");
  // ... perform read-only operations ...
}

const userList = [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }];
processData(userList); // Pass a mutable array to a function expecting readonly

Readonly Tuples

Similar to ReadonlyArray, TypeScript also supports readonly tuples. A readonly tuple ensures that neither its length nor its element types can be changed after creation, offering type-safe immutability for fixed-length sequences.

typescript
type UserInfo = readonly [number, string, boolean];

const user1: UserInfo = [101, "John Doe", true];
// user1[0] = 102; // Error: Index signature in type 'readonly [number, string, boolean]' only permits reading.

Conclusion

Readonly arrays and tuples are invaluable TypeScript features for enhancing code reliability by enforcing immutability. By leveraging them, developers can prevent common bugs related to accidental data modification, leading to more predictable and maintainable applications.