Suggest an editImprove this articleRefine the answer for “What does Readonly<T> do?”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)`Readonly<T>` makes **all properties of an object read-only** - that is, they cannot be changed, redefined, or deleted after the object is created. **Key point:** `Readonly<T>` protects an object's inner fields at the type-system level, while `const` protects only the variable itself (the reference), not its contents.Shown above the full answer for quick recall.Answer (EN)Image## 1. What `Readonly<T>` does > `Readonly<T>` makes **all properties of an object read-only** - > that is, they **cannot be changed, redefined, or deleted** after the object is created. --- ### Example ```javascript interface User { id: number; name: string; } const user: Readonly<User> = { id: 1, name: "Tim", }; user.name = "Max"; // Error: cannot change property "name" ``` > You can read `user.name`, but you cannot change it. > TypeScript throws an error at **compile time**, before the code runs. --- ## 2. How `Readonly<T>` works internally The `Readonly<T>` type is implemented via a **mapped type**: ```javascript type Readonly<T> = { readonly [P in keyof T]: T[P]; }; ``` Explanation: - `keyof T` takes all the keys of type `T`; - `readonly` adds the "read-only" modifier; - `T[P]` preserves the original property type. --- ## 3. How `Readonly<T>` differs from `const` Great question, they are often confused. See the differences below. | Feature | `Readonly<T>` | `const` | | --- | --- | --- | | Applies to | a type (object, interface, generic) | a variable | | Checked | at the **property** level | at the **reference** level | | Protects | the object's internal fields | only the variable itself | | Where it acts | in the type system (TypeScript) | at runtime (JavaScript) | --- ### Comparison example ```javascript const user = { id: 1, name: "Tim" }; user.name = "Max"; // Allowed! ``` > `const` doesn't allow you to **reassign the variable** `user = ...`, > but you can change the object's fields. --- But with `Readonly<T>`: ```javascript const user: Readonly<{ id: number; name: string }> = { id: 1, name: "Tim", }; user.name = "Max"; // Error - the property is readonly ``` > `Readonly<T>` protects the **contents**, > while `const` protects **the variable itself** (the reference). --- ### Combined usage You can combine `const` and `Readonly` for full protection: ```javascript const user: Readonly<{ id: number; name: string }> = { id: 1, name: "Tim", }; ``` > Now: > > - `user` cannot be reassigned (because of `const`); > - `user.name` cannot be changed (because of `Readonly`). --- ## 4. What happens if you try to change a `Readonly<T>` property TypeScript **blocks the change at compile time** - it throws an error like: ```javascript Cannot assign to 'property' because it is a read-only property. ``` --- ### Example ```javascript interface Config { port: number; host: string; } const cfg: Readonly<Config> = { port: 8080, host: "localhost", }; cfg.port = 3000; // Error: the property is read-only ``` > In the compiled JavaScript this is **not blocked at runtime** > (TypeScript removes the types), > but the IDE and compiler **won't let you make the mistake in your code**. --- ## 5. Readonly for arrays You can make an array immutable: ```javascript const nums: ReadonlyArray<number> = [1, 2, 3]; nums.push(4); // Error nums[0] = 10; // Error ``` > You can only read the elements, but not change the structure. --- ## 6. Deep immutability (Deep Readonly) The regular `Readonly<T>` protects **only the top level**. Nested objects **remain mutable**. --- ### Example: ```javascript interface User { id: number; profile: { name: string; city: string; }; } const u: Readonly<User> = { id: 1, profile: { name: "Tim", city: "Kyiv" }, }; u.profile.city = "Paris"; // Allowed! (Readonly is top-level only) ``` --- To forbid changes **inside nested objects**, use **DeepReadonly**: ```javascript type DeepReadonly<T> = { readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]; }; const deepUser: DeepReadonly<User> = { id: 1, profile: { name: "Tim", city: "Kyiv" }, }; deepUser.profile.city = "Paris"; // Error ``` --- ## Summary | Question | Answer | | --- | --- | | What does `Readonly<T>` do | Makes all properties of a type read-only (`readonly`) | | How it differs from `const` | `Readonly` protects **internal fields**, `const` protects **the variable itself** | | What happens when trying to change it | TypeScript throws "Cannot assign to '...' because it is a read-only property" | | Does it work deeply | No, only the top level (for deep protection, use `DeepReadonly<T>`) |For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.