typestar

readonly and immutability in TypeScript

Readonly arrays and objects, and where the guarantee stops.

type Config = { theme: string; langs: string[] };

const frozen: Readonly<Config> = { theme: "dracula", langs: ["ts"] };
// frozen.theme = "x";        // error: readonly
frozen.langs.push("go");      // allowed: only one level deep

function total(values: readonly number[]): number {
  return values.reduce((sum, value) => sum + value, 0);
}

const scores: readonly number[] = [1, 2, 3];
// scores.push(4);            // error: no push on a readonly array
console.log(total(scores), [...scores].reverse());

type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
const deep: DeepReadonly<Config> = { theme: "paper", langs: ["ts"] };
console.log(deep.langs.length, frozen.langs.length);

How it works

  1. readonly T[] has no push, pop or sort.
  2. Readonly<T> freezes one level, like the runtime freeze.
  3. The compile-time check disappears behind an as cast.

Keywords and builtins used here

The run, in numbers

Lines
19
Characters to type
731
Tokens
188
Three-star pace
95 tpm

At the three-star pace of 95 tokens a minute, this run takes about 119 seconds.

Type this snippet

Step 5 of 5 in Objects & interfaces, step 15 of 23 in Types & annotations.

← Previous Next →