Welcome back! I am Mihir, and in this lesson we will learn readonly properties in TypeScript.
readonly prevents accidental reassignment of object properties.
What is readonly?
Use readonly before a property name.
type User = {
readonly id: number;
name: string;
};
const user: User = {
id: 1,
name: "Mihir",
};You can read id:
console.log(user.id);But you cannot change it:
user.id = 2;TypeScript warns because id is readonly.
Why Use readonly?
Use readonly for values that should not change after creation.
Common examples:
- database IDs
- created dates
- configuration values
- route names
- fixed metadata
Example:
type BlogPost = {
readonly slug: string;
title: string;
views: number;
};The title and views may change, but the slug should stay stable.
readonly Does Not Freeze Runtime Objects
Important: readonly is a TypeScript check.
It does not freeze the object at runtime.
type User = {
readonly id: number;
};TypeScript prevents this during development:
user.id = 2;But JavaScript itself still runs without TypeScript types after compilation.
If you need runtime immutability, use JavaScript tools like Object.freeze().
readonly with Nested Objects
readonly only applies to the property itself.
type User = {
readonly profile: {
bio: string;
};
};
const user: User = {
profile: {
bio: "Developer",
},
};This is invalid:
user.profile = { bio: "Writer" };But this is allowed:
user.profile.bio = "Writer";The profile property is readonly, but the nested bio property is not.
Make Nested Properties readonly
If nested values should not change, mark them too.
type User = {
readonly profile: {
readonly bio: string;
};
};Now this is invalid:
user.profile.bio = "Writer";readonly Arrays
You can make arrays readonly.
const roles: readonly string[] = ["admin", "editor", "viewer"];Invalid:
roles.push("guest");
roles.pop();
roles[0] = "owner";Readonly arrays can be read, but not mutated.
ReadonlyArray Syntax
This is another valid syntax:
const roles: ReadonlyArray<string> = ["admin", "editor", "viewer"];Both are fine.
Most beginners find this shorter:
readonly string[]readonly in Function Parameters
Readonly parameters protect input data from mutation.
function printRoles(roles: readonly string[]): void {
roles.forEach((role) => console.log(role));
}Inside the function, this is invalid:
roles.push("guest");The function can read the array but cannot modify it.
Common Mistake: Expecting Deep Immutability
This is not deeply readonly:
type Settings = {
readonly theme: {
mode: string;
};
};Only theme itself cannot be replaced. theme.mode can still change.
Mark nested properties as readonly if needed.
Quick Reference Summary
| Concept | Example |
|---|---|
| Readonly property | readonly id: number |
| Cannot reassign | user.id = 2 is invalid |
| Readonly array | readonly string[] |
| Alternate syntax | ReadonlyArray<string> |
| Runtime freeze | use Object.freeze() |
| Not deep by default | nested fields need readonly too |
Practice
Create a readonly product ID:
type Product = {
readonly id: number;
title: string;
price: number;
};
const product: Product = {
id: 1,
title: "Keyboard",
price: 1499,
};
product.title = "Mechanical Keyboard";Now try changing product.id and check TypeScript's warning.
What You've Learned
You now understand:
- What
readonlymeans - How readonly properties prevent reassignment
- When readonly properties are useful
- Why readonly is a TypeScript check, not a runtime freeze
- How readonly works with nested objects
- How readonly arrays work
- How to use readonly function parameters
What's Next?
In the next lesson, we will learn Union and Literal Types in TypeScript.
We will model values that can be one of several possible options.
Need Help?
- Have questions, confusion, or want to know more? Contact me
readonly is a small keyword with a big job: it protects values that should stay stable.