TypeScript: readonly vs const
In TypeScript, both readonly and const are used to prevent mutation, but they apply to different scopes.
1. The Rule of Thumb
- Use
constfor variables. - Use
readonlyfor properties (of interfaces, classes, or type literals).
2. const (Variables)
const is a JavaScript (ES6) feature. It defines a block-scoped variable that cannot be reassigned.
const x = 10;
// x = 20; // Error: Assignment to constant variable.
Important: const only prevents reassignment of the variable reference. It does not make the object immutable.
const user = { name: "Alice", age: 30 };
// You CANNOT change the reference
// user = { name: "Bob", age: 40 }; // Error
// You CAN change the properties
user.age = 31; // OK
3. readonly (Properties)
readonly is a TypeScript feature. It marks specific properties of an object as immutable.
In Interfaces and Types
interface Point {
readonly x: number;
readonly y: number;
}
let p: Point = { x: 10, y: 20 };
// p.x = 5; // Error: Cannot assign to 'x' because it is a read-only property.
In Classes
Readonly properties in classes can only be initialized at their declaration or inside the constructor.
class Greeter {
readonly greeting: string;
constructor(message: string) {
this.greeting = message;
}
changeGreeting() {
// this.greeting = "Hello"; // Error
}
}
4. Readonly<Type> Utility
If you want to make all properties of an object readonly, you don't need to mark them one by one. You can use the Readonly<T> utility type.
interface User {
name: string;
age: number;
}
const user: Readonly<User> = { name: "Alice", age: 30 };
// user.age = 31; // Error
5. ReadonlyArray<Type>
Standard arrays are mutable. ReadonlyArray<T> (or readonly T[]) removes methods that mutate the array (like push, pop, splice).
const a: number[] = [1, 2, 3];
const ro: ReadonlyArray<number> = a;
// ro[0] = 12; // Error
// ro.push(5); // Error
// Non-mutating methods are fine
console.log(ro.length);
console.log(ro.slice(1));
6. Summary
| Feature | const |
readonly |
|---|---|---|
| Target | Variables | Object Properties |
| Origin | JavaScript (Runtime) | TypeScript (Compile-time) |
| Behavior | Prevents reassignment | Prevents property mutation |
| Deep Immutability? | No | No (unless recursive) |