Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Незмінні поля». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)Щоб зробити властивість **незмінною**, в інтерфейсі або типі перед її ім'ям пишуть ключове слово `readonly`. Воно гарантує, що властивість не можна переозначити після ініціалізації, а спроба змінити значення викличе помилку компіляції. **Ключове:** `readonly` захищає лише верхній рівень об'єкта - вкладені поля залишаються змінними, якщо не використати рекурсивний тип на кшталт `DeepReadonly`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Ключове слово `readonly` Щоб зробити властивість **незмінною**, в інтерфейсі або типі перед її ім'ям пишуть ключове слово `readonly`. --- ### У **інтерфейсі** ```javascript interface User { readonly id: number; name: string; } const user: User = { id: 1, name: "Tim" }; user.name = "Max"; // можна змінити user.id = 2; // Помилка: властивість лише для читання ``` > `readonly` гарантує, що `id` не можна переозначити після ініціалізації. > Спроба змінити значення викличе помилку компіляції. --- ### У **типі (**`type`**)** ```javascript type Product = { readonly sku: string; title: string; }; const item: Product = { sku: "A-123", title: "Linen shirt" }; item.title = "Cotton shirt"; // можна item.sku = "B-456"; // Помилка ``` > Працює точно так само, як в інтерфейсах. --- ## 2. Незмінність поширюється лише на **верхній рівень** TypeScript робить `readonly` лише для самої властивості, але не захищає **вкладені об'єкти**: ```javascript interface Profile { readonly user: { name: string; }; } const p: Profile = { user: { name: "Tim" } }; p.user = { name: "Max" }; // Помилка (не можна перепризначити user) p.user.name = "Max"; // допустимо (вкладені поля можна змінювати) ``` > Тобто "глибока" незмінність не створюється автоматично. --- ## 3. Як зробити *всі* поля незмінними TypeScript надає вбудований **утилітний тип** `Readonly<T>`, який перетворює всі властивості типу `T` на `readonly`. ```javascript interface User { id: number; name: string; } type ImmutableUser = Readonly<User>; const user: ImmutableUser = { id: 1, name: "Tim" }; user.id = 2; // Помилка user.name = ""; // Помилка ``` > `Readonly<T>` автоматично додає `readonly` перед кожним полем інтерфейсу. --- ## 4. Як зробити "глибоку" незмінність (вкладені поля теж readonly) TypeScript із коробки робить лише **поверхневу** (shallow) незмінність. Якщо потрібно заборонити зміну **вкладених об'єктів**, використовують рекурсивні утиліти - наприклад, через `DeepReadonly`. ### Приклад реалізації: ```javascript type DeepReadonly<T> = { readonly [K in keyof T]: DeepReadonly<T[K]>; }; ``` ### Приклад використання: ```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; // Помилка u.profile.name = "Max"; // Помилка u.profile.address.city = "NY"; // Помилка ``` > Тепер об'єкт і всі його вкладені поля - **справді незмінні**. --- ## 5. `readonly` також працює з масивами Ти можеш зробити **масив лише для читання** за допомогою `readonly` або `ReadonlyArray<T>`: ```javascript const nums: readonly number[] = [1, 2, 3]; nums.push(4); // Помилка const names: ReadonlyArray<string> = ["Tim", "Max"]; names[0] = "Anton"; // Помилка ``` > Такий масив не можна модифікувати (додавати, прибирати чи змінювати елементи), > але можна читати. --- ## 6. Зведена таблиця | Що потрібно зробити | Як записати | Приклад | |---|---|---| | Одна властивість лише для читання | `readonly id: number` | `interface User { readonly id: number }` | | Усі властивості readonly | `Readonly<Type>` | `type Immutable = Readonly<User>` | | Глибока незмінність | `DeepReadonly<T>` | рекурсивний тип | | Масив лише для читання | `readonly T[]` або `ReadonlyArray<T>` | `readonly number[]` | --- ## Підсумок > У TypeScript **незмінні властивості** задаються через `readonly`. > > В інтерфейсі: > > ```javascript > interface User { readonly id: number } > ``` > > У типі: > > ```javascript > type User = { readonly id: number } > ``` > > Для всіх полів: > > ```javascript > type Frozen = Readonly<User> > ``` > > Це допомагає писати **надійний, передбачуваний і безпечний код**, > захищаючи дані від випадкових змін.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.