Learn how to define immutable properties in TypeScript classes using the readonly keyword. Understand the differences between readonly and const, and explore practical use cases for immutability.
In this section, we will explore the concept of readonly properties in TypeScript classes. Readonly properties are a powerful feature that allows developers to define properties that cannot be modified after they have been initialized. This immutability can help prevent accidental changes to critical data and make your code more robust and predictable.
readonly
KeywordThe readonly
keyword in TypeScript is used to create properties within a class that cannot be reassigned after their initial assignment. This is particularly useful when you want to ensure that certain properties remain constant throughout the lifecycle of an object.
To declare a readonly property, simply prefix the property name with the readonly
keyword. Here’s a simple example:
class Car {
readonly make: string;
readonly model: string;
readonly year: number;
constructor(make: string, model: string, year: number) {
this.make = make;
this.model = model;
this.year = year;
}
}
const myCar = new Car('Toyota', 'Corolla', 2020);
console.log(myCar.make); // Output: Toyota
// Attempting to modify a readonly property will result in an error
// myCar.make = 'Honda'; // Error: Cannot assign to 'make' because it is a read-only property.
In this example, the properties make
, model
, and year
are marked as readonly
, meaning they can only be set once, typically in the constructor.
const
It’s important to understand the difference between readonly
and const
. While both are used to enforce immutability, they are applied in different contexts:
const
: Used for variables whose values cannot be reassigned. It is used at the variable level and is not applicable to class properties.
const pi = 3.14;
// pi = 3.14159; // Error: Cannot assign to 'pi' because it is a constant.
readonly
: Used for class properties that should not be reassigned after initialization. It allows for the initialization of properties within the constructor.
Readonly properties are typically initialized in the constructor of a class. This allows you to set their values when creating an instance of the class, ensuring that they remain immutable thereafter.
Here’s an example demonstrating how to set readonly properties through a constructor:
class Book {
readonly title: string;
readonly author: string;
constructor(title: string, author: string) {
this.title = title;
this.author = author;
}
}
const myBook = new Book('1984', 'George Orwell');
console.log(myBook.title); // Output: 1984
// myBook.title = 'Animal Farm'; // Error: Cannot assign to 'title' because it is a read-only property.
In this example, the title
and author
properties are initialized in the constructor and cannot be changed afterward.
Readonly properties are particularly useful in scenarios where immutability is desired. Here are some common use cases:
Constants: Use readonly properties to define constant values that should not change, such as configuration settings or fixed data.
Immutable Data Structures: When creating data structures that should not be altered after creation, readonly properties ensure that the data remains consistent.
Preventing Accidental Changes: By marking properties as readonly, you can prevent accidental modifications that could lead to bugs or inconsistent state.
Enhancing Code Predictability: Immutability can make your code more predictable and easier to reason about, as you can be confident that certain values will not change unexpectedly.
Immutability is a key principle in functional programming and can lead to more reliable and maintainable code. By using readonly properties, you can enforce immutability in your classes and take advantage of its benefits.
Let’s create a configuration object that uses readonly properties to ensure its values remain constant:
class AppConfig {
readonly apiUrl: string;
readonly maxRetries: number;
constructor(apiUrl: string, maxRetries: number) {
this.apiUrl = apiUrl;
this.maxRetries = maxRetries;
}
}
const config = new AppConfig('https://api.example.com', 3);
console.log(config.apiUrl); // Output: https://api.example.com
// config.apiUrl = 'https://api.newexample.com'; // Error: Cannot assign to 'apiUrl' because it is a read-only property.
In this example, the AppConfig
class defines an immutable configuration object with apiUrl
and maxRetries
as readonly properties.
To reinforce your understanding of readonly properties, try modifying the examples above. Experiment with adding new readonly properties or attempting to change their values after initialization. Observe the errors that TypeScript provides and consider how readonly properties can enhance the reliability of your code.
To better understand how readonly properties work within a class, let’s visualize the flow of data using a simple diagram.
classDiagram class Car { +readonly make: string +readonly model: string +readonly year: number +Car(make: string, model: string, year: number) }
In this diagram, the Car
class is shown with its readonly properties. The +
symbol indicates that these properties are public and accessible from outside the class, but they cannot be modified after the object is created.
Readonly properties in TypeScript provide a powerful way to enforce immutability within your classes. By using the readonly
keyword, you can ensure that certain properties remain constant after initialization, preventing accidental changes and enhancing the predictability of your code.
Key Takeaways:
readonly
keyword to define immutable properties in a class.readonly
and const
.For more information on readonly properties and immutability in TypeScript, consider exploring the following resources: