JavaScript's Object.freeze and TypeScript's Readonly
By Dale Jefferson. Published
Do you want static or runtime immutability, or both? In this article I will show you how to combine Object.freeze with Readonly to get the best of both worlds.
JavaScript’s Object.freeze
JavaScript’s Object.freeze()
function provides runtime immutability (at a minor performance cost). You have a 100% guarantee your array or object will not change underneath you.
const austrians = Object.freeze([
Object.freeze({name: "Carl Menger"}),
Object.freeze({name: "Eugen Böhm von Bawerk"}),
Object.freeze({name: "Ludwig von Mises"})
]);
austrians.push({name: "John Maynard Keynes"}); // Runtime Error
austrians[0].name = "John Maynard Keynes"; // Runtime Error
TypeScript’s Readonly
TypeScript’s Readonly<T>
generic type provides static type immutability which has zero performance overhead. At runtime the array or object can change, so this only works if all your code is TypeScript.
interface Austrian {
readonly name: string;
}
const austrians: ReadonlyArray<Austrian> = [
{name: "Carl Menger"},
{name: "Eugen Böhm von Bawerk"},
{name: "Ludwig von Mises"}
];
austrians.push({name: "John Maynard Keynes"}); // Compile error
austrians[0].name = "John Maynard Keynes"; // Compile error
TypeScript ❤️ JavaScript
These two tools are not mutually exclusive you can combine Static typing immutability & runtime immutability.
interface Austrian {
readonly name: string;
}
const austrians: ReadonlyArray<Austrian> = Object.freeze([
Object.freeze({name: "Carl Menger"}),
Object.freeze({name: "Eugen Böhm von Bawerk"}),
Object.freeze({name: "Ludwig von Mises"})
]);
austrians.push({name: "John Maynard Keynes"}); // Everything error
austrians[0].name = "John Maynard Keynes"; // Everything error