Skip to main content

Незмінні поля

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: numberinterface User { readonly id: number }
Усі властивості readonlyReadonly<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>

Це допомагає писати надійний, передбачуваний і безпечний код, захищаючи дані від випадкових змін.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.