Suggest an editImprove this articleRefine the answer for “Immutable fields”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)To make a property **immutable**, you write the `readonly` keyword before its name in an interface or a type. It guarantees that the property cannot be reassigned after initialization, and attempting to change the value causes a compilation error. **Key point:** `readonly` only protects the top level of an object - nested fields remain mutable unless you use a recursive type such as `DeepReadonly`.Shown above the full answer for quick recall.Answer (EN)Image## 1. The `readonly` keyword To make a property **immutable**, you write the `readonly` keyword before its name in an interface or a type. --- ### In an **interface** ```javascript interface User { readonly id: number; name: string; } const user: User = { id: 1, name: "Tim" }; user.name = "Max"; // can be changed user.id = 2; // Error: read-only property ``` > `readonly` guarantees that `id` cannot be reassigned after initialization. > Attempting to change the value causes a compilation error. --- ### In a **type (**`type`**)** ```javascript type Product = { readonly sku: string; title: string; }; const item: Product = { sku: "A-123", title: "Linen shirt" }; item.title = "Cotton shirt"; // allowed item.sku = "B-456"; // Error ``` > Works exactly the same way as in interfaces. --- ## 2. Immutability applies only at the **top level** TypeScript makes `readonly` apply only to the property itself, but does not protect **nested objects**: ```javascript interface Profile { readonly user: { name: string; }; } const p: Profile = { user: { name: "Tim" } }; p.user = { name: "Max" }; // Error (cannot reassign user) p.user.name = "Max"; // allowed (nested fields can be changed) ``` > In other words, "deep" immutability is not created automatically. --- ## 3. How to make *all* fields immutable TypeScript provides a built-in **utility type** `Readonly<T>`, which turns every property of type `T` into `readonly`. ```javascript interface User { id: number; name: string; } type ImmutableUser = Readonly<User>; const user: ImmutableUser = { id: 1, name: "Tim" }; user.id = 2; // Error user.name = ""; // Error ``` > `Readonly<T>` automatically adds `readonly` before every field of the interface. --- ## 4. How to make "deep" immutability (nested fields too) Out of the box, TypeScript only gives you **shallow** immutability. If you need to prevent changes to **nested objects**, you use recursive utilities, for example `DeepReadonly`. ### Example implementation: ```javascript type DeepReadonly<T> = { readonly [K in keyof T]: DeepReadonly<T[K]>; }; ``` ### Example usage: ```javascript interface User { id: number; profile: { name: string; address: { city: string; }; }; } type FrozenUser = DeepReadonly<User>; const u: FrozenUser = { id: 1, profile: { name: "Tim", address: { city: "LA" } }, }; u.id = 2; // Error u.profile.name = "Max"; // Error u.profile.address.city = "NY"; // Error ``` > Now the object and all its nested fields are **truly immutable**. --- ## 5. `readonly` also works with arrays You can make an **array read-only** using `readonly` or `ReadonlyArray<T>`: ```javascript const nums: readonly number[] = [1, 2, 3]; nums.push(4); // Error const names: ReadonlyArray<string> = ["Tim", "Max"]; names[0] = "Anton"; // Error ``` > Such an array cannot be modified (elements cannot be added, removed, or changed), > but it can be read. --- ## 6. Summary table | What you need | How to write it | Example | |---|---|---| | One read-only property | `readonly id: number` | `interface User { readonly id: number }` | | All properties readonly | `Readonly<Type>` | `type Immutable = Readonly<User>` | | Deep immutability | `DeepReadonly<T>` | recursive type | | Read-only array | `readonly T[]` or `ReadonlyArray<T>` | `readonly number[]` | --- ## Summary > In TypeScript, **immutable properties** are defined through `readonly`. > > In an interface: > > ```javascript > interface User { readonly id: number } > ``` > > In a type: > > ```javascript > type User = { readonly id: number } > ``` > > For all fields: > > ```javascript > type Frozen = Readonly<User> > ``` > > This helps write **reliable, predictable, and safe code**, > protecting data from accidental changes.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.