Незмінні поля
1. Ключове слово readonly
Щоб зробити властивість незмінною,
в інтерфейсі або типі перед її ім'ям пишуть ключове слово readonly.
У інтерфейсі
interface User {
readonly id: number;
name: string;
}
const user: User = { id: 1, name: "Tim" };
user.name = "Max"; // можна змінити
user.id = 2; // Помилка: властивість лише для читання
readonlyгарантує, щоidне можна переозначити після ініціалізації. Спроба змінити значення викличе помилку компіляції.
У типі (type)
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 лише для самої властивості,
але не захищає вкладені об'єкти:
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.
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.
Приклад реалізації:
type DeepReadonly<T> = {
readonly [K in keyof T]: DeepReadonly<T[K]>;
};Приклад використання:
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>:
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.В інтерфейсі:
javascriptinterface User { readonly id: number }У типі:
javascripttype User = { readonly id: number }Для всіх полів:
javascripttype Frozen = Readonly<User>Це допомагає писати надійний, передбачуваний і безпечний код, захищаючи дані від випадкових змін.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.