Readonly Properties of Object in TypeScript: Explained with Examples

Updated: January 7, 2024 By: Guest Contributor Post a comment

Introduction

Among TypeScript’s bounteous gifts to the diligent codifiers of the digital dominion is the ability to crown properties of objects with the princely attribute of immutability. This paramount feature enables developers to fashion objects as solid and unchanging as monuments, ensuring consistency across the application’s expanse.

Readonly in TypeScript: A Primer

In TypeScript’s lexicon, ‘readonly’ is the keyword used to compose a promise that once a property has been set, no force, high or low, should dare to alter its state. Upon instantiation, these properties accept their lifelong values, stalwart in the face of modification attempts that would wrest them from their declared constancy.


class Ledger {
    readonly id: number;
    readonly name: string;

    constructor(id: number, name: string) {
        this.id = id;
        this.name = name;
    }
}

const account = new Ledger(1, "Tom's Ledger");
account.id = 2; // Compiler will rebuke this attempt with stern disapproval

Defining Readonly Properties in Interfaces

Interfaces in TypeScript, being akin to oaths taken by objects, may too profess properties as ‘readonly’. This ensures that all manner of shapes adhering to the interface honor the pact of unalterableness.


interface ImmutablePoint {
    readonly x: number;
    readonly y: number;
}

let point: ImmutablePoint = { x: 10, y: 20 };
point.x = 30; // The code doth protest, refusing the change

Readonly Arrays: Immutable Collections

TypeScript extends the dominion of ‘readonly’ to the storied lands of arrays, bestowing upon them a fixed order and content as intractable as the chiseled edicts of old.


let ledgerEntries: ReadonlyArray = [1, 2, 3];
ledgerEntries.push(4); // Hear ye, the compiler's objection shall ring loud and clear

Readonly and Generic Types

Generic types, those versatile molds from which types of myriad shapes are born, may too be graced with ‘readonly’ properties. It enforces a gentle but firm rule upon the fields of any candidate donning the generic mantle.


class UniversalLedger {
    readonly entry: T;

    constructor(entry: T) {
        this.entry = entry;
    }
}

const numericalLedger = new UniversalLedger(1000);
numericalLedger.entry = 2000; // Attempting change shall usher in the compiler's scorn

Transforming Mutable Types to Readonly

When a mutable type must pass through the alchemic transformation to don a robe of immutability, TypeScript offers the utility type ‘Readonly’. Thus, an object once given to change is reborn into immutable splendor.


type MutablePoint = { x: number; y: number };
type FixedPoint = Readonly;

const mutablePoint: MutablePoint = { x: 0, y: 0 };
const immutablePoint: FixedPoint = mutablePoint;
immutablePoint.x = -1; // The compiler shall not entertain such whims

Using Readonly in Class Methods

Class methods may honor the sanctity of readonly properties, assuring that treacherous hands find no purchase on values set in temporal stone.


class UnchangingNotes {
    readonly note: string;

    constructor(note: string) {
        this.note = note;
    }

    updateNote(newNote: string): void {
        // this.note = newNote; // Un-comment this line, and the compiler shall unleash its fury
    }
}

Conclusion

In conclusion, TypeScript’s ‘readonly’ mandate serves as a solemn vow, a safeguard against the forces of change that would unseat values ordained to be eternal. By using ‘readonly’, developers may sculpt data structures as inviolate as the ancient pyramids—defiant against the deserts of mutation. Adopting this feature is not merely a technical choice, but a philosophical stand, enshrining the trust between a system’s designers and its users in unbreakable code.