Skip to Content
Course content

21: Readonly Properties

Click on the "Edit" button in the top corner of the screen to edit your slide content.

By now, you're probably used to using const to keep your variables from being reassigned. But when you're dealing with classes or interfaces, const doesn't work on individual properties. That's where readonly comes in.

Why use readonly instead of just avoiding a setter?

In a plain JavaScript class, you might just not provide a setter method, or you might use a private field with a getter. But in TypeScript, readonly is a signal to the compiler. It tells anyone using your class—including your future self—that this property is meant to be set once and then left alone.

Take a User account system, for example. You want the userId to be immutable because changing a primary key mid-session is a recipe for a database nightmare.

class UserAccount {
  readonly userId: string;
  username: string;

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

const user = new UserAccount("usr_12345", "DevDan");
user.username = "DanTheCoder"; // This is fine
user.userId = "usr_99999";     // Error: Cannot assign to 'userId' because it is a read-only property.

The beauty here is that the error happens in your IDE, not at runtime. You don't have to wait for a bug to hit production to realize you accidentally overwrote a critical ID.

Wait, how is this different from using const?

This is a common point of confusion. Think of it this way: const is for variables; readonly is for properties.

You can't put const inside a class definition. If you try, TypeScript will scream at you. readonly is specifically designed for the members of a class or the fields of an interface. I usually use readonly for "configuration" style data—things that are determined at the moment an object is created and should stay that way for the rest of the object's lifecycle.

If I mark an array as readonly, can I still push items into it?

Here is the "gotcha" I always warn people about. If you mark a property as readonly, you can't reassign the property to a new array, but you can still mutate the contents of that array.

interface AppConfig {
  readonly plugins: string[];
}

const config: AppConfig = {
  plugins: ["Auth", "Logging"]
};

config.plugins = ["NewPlugin"]; // Error: Readonly property
config.plugins.push("Analytics"); // This actually WORKS.

If you want the actual contents of the array to be immutable, you need to use the ReadonlyArray type (or the readonly string[] shorthand). I highly recommend doing this if you're building a system where data integrity is critical. It forces you to create a new array instead of mutating the existing one, which is a much safer pattern in modern JS/TS.

Can I ever change a readonly property after the class is initialized?

Short answer: No. The only place a readonly property can be assigned is inside the constructor. Once the constructor finishes executing, that property is locked down.

If you find yourself wanting to change a readonly property later, you're probably dealing with a state change that shouldn't be readonly, or you should be creating a new instance of the object entirely. Don't try to "cheat" the system by casting to any just to change a value; that defeats the entire purpose of using TypeScript in the first place.




📋 Practical Task

Exercise: Securing the GameSession Configuration

You are building a game engine. Each GameSession should have a unique sessionId and a difficulty setting that cannot be changed once the game has started. However, the currentScore should be updateable as the player progresses.

Your Task:

  • Create a GameSession class.
  • Add a sessionId property (string) and a difficulty property (string). Both must be immutable after instantiation.
  • Add a currentScore property (number) that can be modified.
  • Implement a constructor to initialize all three values.
  • Instantiate the class and attempt to change the sessionId to verify that TypeScript throws an error.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.