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
readonly T[]has no push, pop or sort.Readonly<T>freezes one level, like the runtime freeze.- The compile-time check disappears behind an
ascast.
Keywords and builtins used here
DeepReadonlyReadonlyconstextendsfunctionnumberreadonlyreturnstringtype
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.
Step 5 of 5 in Objects & interfaces, step 15 of 23 in Types & annotations.