Typescript Readonly And Static Properties Complete Guide
Understanding the Core Concepts of TypeScript Readonly and Static Properties
Readonly Properties
Readonly properties provide a way to lock the value of a property after it has been initialized in a class constructor or as a class property. It is a powerful feature for ensuring that certain properties are not modified after their initial assignment, which aligns with immutability principles often seen in functional programming.
Explanation:
- Usage: The
readonly
modifier is added to any property within a class definition to indicate its value should not change once set. - Initialization: A
readonly
property must be initialized either at the time of declaration or in the class constructor.
Syntax:
class Employee {
readonly empNo: number;
readonly empName: string;
constructor(employeeNumber: number, employeeName: string) {
this.empNo = employeeNumber;
this.empName = employeeName;
}
}
In the above code:
empNo
andempName
are marked asreadonly
, meaning they cannot be altered after the instance is created.- If you attempt to reassign the value of
empNo
orempName
on an instance ofEmployee
, TypeScript will throw a compile-time error.
Benefits:
- Enforce Immutable Data: Ensures that the data integrity is maintained and prevents accidental modifications.
- Improved Predictability: Increases predictability by guaranteeing that certain values will remain constant throughout the lifecycle of an object, reducing potential bugs.
Static Properties
Static properties, on the other hand, belong to the class itself rather than to any specific instance of the class. This means they are shared across all instances of the class and can also be accessed directly from the class without needing to instantiate it.
Explanation:
- Usage: The
static
keyword is used to define a static property within a class. - Access: Static properties can be accessed using the class name followed by a dot syntax.
Syntax:
class MathUtility {
static PI: number = 3.14159;
static areaOfCircle(radius: number): number {
return radius * radius * MathUtility.PI;
}
}
console.log(MathUtility.PI); // Accessing static property directly via class name
console.log(MathUtility.areaOfCircle(5)); // Calling static method directly via class name
In the example provided:
PI
is a static property shared among all instances ofMathUtility
.- The
areaOfCircle
method is also static and utilizes thePI
constant directly without requiring an instance ofMathUtility
.
Benefits:
- Shared Across Instances: Useful for utility functions or properties that are common to all instances of a class, promoting memory efficiency.
- Direct Accessibility: Allows direct access to the class's functionality without needing to create an instance first.
Combination of Readonly and Static Properties
You can also combine readonly
with static
to create a static property that is both immutable and shared among class instances.
Syntax:
class AppConfig {
static readonly BASE_API_URL: string = 'https://api.example.com/';
}
console.log(AppConfig.BASE_API_URL); // Outputs: https://api.example.com/
// AppConfig.BASE_API_URL = 'https://new.example.com/'; // This will cause a compile-time error as BASE_API_URL is readonly
In the AppConfig
class:
BASE_API_URL
is a static readonly property, meaning its value cannot be changed after it is initialized.
Use Case: This approach is ideal for configuration values such as API endpoints, default settings, etc., where you want these values to be consistent and immutable throughout the application life cycle.
Summary of Key Points
- Readonly: Locks the value of a property, providing immutability and helping prevent accidental changes.
- Static: Belongs to the class itself rather than individual instances, allowing shared state and methods.
- Readonly-Static: Combines both features for properties shared and immutable at the class level.
Online Code run
Step-by-Step Guide: How to Implement TypeScript Readonly and Static Properties
TypeScript Readonly Properties
readonly
properties allow you to define a class member that cannot be changed once it is set during the initialization of the object.
Step-by-Step Example:
Define the Class: Start by creating a simple class called
Product
.Add a
readonly
Property: Add areadonly
property to the class namedproductID
.Initialize the
readonly
Property: Initialize thereadonly
property through the constructor.
Code:
// Step 1: Define the class Product
class Product {
// Step 2: Add readonly property productID
readonly productID: number;
// Other non-readonly properties
name: string;
price: number;
// Step 3: Initialize the readonly property
constructor(id: number, name: string, price: number) {
this.productID = id;
this.name = name;
this.price = price;
}
// Method to print product information
getProductInfo() {
console.log(`Product ID: ${this.productID}, Name: ${this.name}, Price: $${this.price}`);
}
}
// Create an instance of Product
const product = new Product(101, 'Laptop', 999);
// Try to change productID (will cause a compilation error)
// product.productID = 102; // Uncommenting this line will result in an error
// You can still access and use productID, but not change it
product.getProductInfo(); // Output: Product ID: 101, Name: Laptop, Price: $999
Explanation:
- Step 1: We create a class named
Product
. Classes are blueprints for objects in TypeScript. - Step 2: We declare a property named
productID
with thereadonly
keyword. This property cannot be modified after it is set. - Step 3: In the constructor, we initialize the
productID
. Note that you can only assign a value to areadonly
property within the constructor or directly at its declaration. - When you try to modify
productID
outside the constructor (as shown in the commented line), TypeScript will throw a compilation error indicating that assignment is not allowed to a readonly property.
TypeScript Static Properties
static
properties belong to the class itself rather than the instances of the class. They are shared among all instances of the class.
Step-by-Step Example:
Create the Class: Define a class named
Employee
.Add a
static
Property: Add astatic
property namedcompanyName
.Access the
static
Property: Access thestatic
property both inside the class and outside the class using the class name.
Code:
Top 10 Interview Questions & Answers on TypeScript Readonly and Static Properties
1. What are readonly
properties in TypeScript, and how do they differ from regular properties?
Answer:
In TypeScript, readonly
properties are used to indicate that a member of the class (typically a property) should not be modified after its initial assignment, either within the constructor or directly on the instance. Unlike regular properties which can be changed at any point after their initialization, readonly
properties provide an immutability layer ensuring that the original value remains unchanged through the lifecycle of the object.
class Config {
readonly apiEndpoint: string; // This cannot be reassigned outside the constructor
constructor(apiEndpoint: string) {
this.apiEndpoint = apiEndpoint;
}
}
const settings = new Config("https://example.com/api");
settings.apiEndpoint = "https://example.org/api"; // Error: Cannot assign to 'apiEndpoint' because it is a read-only property.
2. Can you use readonly
with both fields and parameters in TypeScript constructors?
Answer:
Yes, TypeScript allows you to use readonly
with both class fields and constructor parameters. Using readonly
directly in the constructor parameter list automatically creates a readonly
field with the same name and assigns it the value of that parameter. This shorthand simplifies the code.
class User {
readonly username: string;
readonly email: string;
constructor(username: string, email: string) {
this.username = username;
this.email = email;
}
}
// Simplified constructor using readonly parameters
class UserSimplified {
constructor(readonly username: string, readonly email: string) {}
}
const bob = new UserSimplified("bob", "bob@example.com");
bob.username = "bobby"; // Error: 'username' is a read-only property.
3. How can static properties be accessed in TypeScript, and what is their purpose?
Answer: Static properties are shared across all instances of a class rather than being unique to an individual instance. They are commonly used for constants or utility functions related to the class but not specific to the instantiated objects. Static properties can be accessed without creating an instance of the class and are typically useful for defining class-related constants.
To access static properties, you use the class name followed by the dot operator and the property name.
class Circle {
static pi = 3.142;
constructor(public radius: number) {}
area(): number {
return this.radius * this.radius * Circle.pi; // Use Circle.pi instead of this.pi
}
}
console.log(Circle.pi); // Output: 3.142
const myCircle = new Circle(5);
console.log(myCircle.area()); // Output: 78.55
The pi
property here is accessible globally via Circle.pi
, not requiring any instance creation.
4. Is it possible to modify static properties after they are defined in TypeScript?
Answer: Yes, static properties can be modified just like regular properties but these modifications affect all instances that share the static property.
class Vehicle {
static numOfVehicles = 0;
constructor() {
Vehicle.numOfVehicles++;
}
}
console.log(Vehicle.numOfVehicles); // Output: 0
const car1 = new Vehicle();
console.log(Vehicle.numOfVehicles); // Output: 1
Vehicle.numOfVehicles = 5; // Manual modification
const car2 = new Vehicle();
console.log(Vehicle.numOfVehicles); // Output: 6 (not 2)
Here, numOfVehicles
is a static property that counts the number of vehicle instances created. It can be changed manually, affecting future vehicle count calculations.
5. What happens if you combine readonly
with static
in a TypeScript class?
Answer:
When readonly
is combined with static
, it creates a static property whose value cannot be changed after its initial assignment. Just like non-static readonly
properties, static readonly
properties must be initialized at the time of declaration or within the constructor itself.
class MathConstants {
static readonly e = Math.E; // Euler's number e
static readonly pi = Math.PI; // PI
constructor() {} // No need to reinitialize static readonly properties
}
console.log(MathConstants.e); // Output: 2.718281828459045
console.log(MathConstants.pi); // Output: 3.141592653589793
MathConstants.pi = 3.14; // Error: Cannot assign to 'pi' because it is a read-only property.
6. Are readonly
and static
modifiers exclusive or can they be used together?
Answer:
No, readonly
and static
are not mutually exclusive; they can be used together in TypeScript to define a constant that is shared among all instances of the class.
Example provided in Q5 illustrates this well.
7. Can private class members be both readonly
and static
in TypeScript?
Answer:
Yes, private members can also be both static
and readonly
. This encapsulates the private static read-only property within the class definition making it only accessible from methods and other static members inside the class.
class Logger {
private static readonly timestampFormat = "HH:mm:ss";
log(message: string) {
const timestamp = new Date().toISOString().slice(-13, -1); // Assuming this returns the format
console.log(`[${timestamp}] ${message}`);
}
}
// Logger.timestampFormat = "HH:mm"; // Error: because it is private
8. How do abstract classes utilize readonly
and static
properties in TypeScript?
Answer:
Abstract classes can also define readonly
and static
properties. These properties can be inherited by child classes but, following the rules of readonly
and static
, cannot be reassigned unless they are overridden and declared again in the derived class.
abstract class BaseConfig {
static readonly defaultTimeout = 2000;
protected readonly serviceUrl: string;
constructor(serviceUrl: string) {
this.serviceUrl = serviceUrl;
}
}
class ProdConfig extends BaseConfig {
static readonly defaultTimeout = 5000;
override readonly serviceUrl = "https://prod.example.com";
constructor() {
super(ProdConfig.defaultTimeout.toString());
}
}
console.log(BaseConfig.defaultTimeout); // Output: 2000
console.log(ProdConfig.defaultTimeout); // Output: 5000
const prodConf = new ProdConfig();
console.log(prodConf.serviceUrl); // Output: "https://prod.example.com"
prodConf.serviceUrl = "new-url"; // Error: 'serviceUrl' is a read-only property.
In the example above, defaultTimeout
is a static, readonly property shared among various configurations. Each configuration class can modify its value as needed.
9. Are readonly
or static
modifiers available for method parameters in TypeScript?
Answer:
Neither readonly
nor static
are applicable to method parameters in TypeScript. Method parameters represent local variables within the scope of the method and thus should not be labeled as readonly
or static
.
class Greet {
greet(readonly name: string) { // Error: A parameter property may not be declared using 'readonly'.
console.log(name);
}
static announce(static message: string) { // Error: 'static' modifier cannot appear on a parameter.
console.log(message);
}
}
10. When should you prefer using readonly
over const
in TypeScript?
Answer:
While both readonly
and const
enforce immutability, their usage differs based on scope:
const
: Use in variable declarations when the variable does not change after its initial assignment within the file. It applies to primitive types as well as object reference.readonly
: Use on class properties when ensuring that a given property value remains constant throughout an object’s lifespan.
Login to post a comment.