Що робить Readonly<T>?
1. Що робить Readonly<T>
Readonly<T>робить усі властивості об'єкта доступними лише для читання - тобто їх не можна змінювати, перевизначати чи видаляти після створення об'єкта.
Приклад
interface User {
id: number;
name: string;
}
const user: Readonly<User> = {
id: 1,
name: "Tim",
};
user.name = "Max"; // Помилка: не можна змінити властивість "name"Можна читати
user.name, але не можна змінювати. TypeScript видає помилку ще на етапі компіляції, до запуску коду.
2. Як Readonly<T> влаштований усередині
Тип Readonly<T> реалізований через mapped type:
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};Пояснення:
keyof T- бере всі ключі типуT;readonly- додає модифікатор "лише для читання";T[P]- зберігає оригінальний тип властивості.
3. Чим Readonly<T> відрізняється від const
Чудове питання - їх часто плутають. Дивись відмінності нижче.
| Особливість | Readonly<T> | const |
|---|---|---|
| Застосовується до | типу (об'єкта, інтерфейсу, generic) | змінної |
| Перевіряється | на рівні властивостей | на рівні посилання |
| Захищає | внутрішні поля об'єкта | лише саму змінну |
| Місце дії | у системі типів (TypeScript) | у рантаймі (JavaScript) |
Приклад порівняння
const user = { id: 1, name: "Tim" };
user.name = "Max"; // Дозволено!
constне дозволяє перепризначити зміннуuser = ..., але змінювати поля об'єкта можна.
А ось з Readonly<T>:
const user: Readonly<{ id: number; name: string }> = {
id: 1,
name: "Tim",
};
user.name = "Max"; // Помилка - властивість readonly
Readonly<T>захищає вміст, аconst- саму змінну (посилання).
Комбіноване використання
Можна поєднати const і Readonly для повного захисту:
const user: Readonly<{ id: number; name: string }> = {
id: 1,
name: "Tim",
};Тепер:
userне можна перепризначити (черезconst);user.nameне можна змінити (черезReadonly).
4. Що станеться, якщо спробувати змінити властивість Readonly<T>
TypeScript заблокує зміну на етапі компіляції - видасть помилку на кшталт:
Cannot assign to 'property' because it is a read-only property.Приклад
interface Config {
port: number;
host: string;
}
const cfg: Readonly<Config> = {
port: 8080,
host: "localhost",
};
cfg.port = 3000; // Помилка: властивість лише для читанняУ скомпільованому JavaScript це не блокується на рівні виконання (TypeScript видаляє типи), але IDE і компілятор не дозволять тобі допустити помилку в коді.
5. Readonly для масивів
Можна зробити масив незмінним:
const nums: ReadonlyArray<number> = [1, 2, 3];
nums.push(4); // Помилка
nums[0] = 10; // ПомилкаМожна лише читати елементи, але не змінювати структуру.
6. Глибока незмінність (Deep Readonly)
Звичайний Readonly<T> захищає лише верхній рівень.
Вкладені об'єкти залишаються змінюваними.
Приклад:
interface User {
id: number;
profile: {
name: string;
city: string;
};
}
const u: Readonly<User> = {
id: 1,
profile: { name: "Tim", city: "Kyiv" },
};
u.profile.city = "Paris"; // Дозволено! (Readonly лише верхній рівень)Щоб заборонити зміни всередині вкладених об'єктів, використай DeepReadonly:
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"; // ПомилкаПідсумок
| Питання | Відповідь |
|---|---|
Що робить Readonly<T> | Робить усі властивості типу лише для читання (readonly) |
Чим відрізняється від const | Readonly захищає внутрішні поля, const - саму змінну |
| Що станеться при спробі змінити | TypeScript видасть помилку "Cannot assign to '...' because it is a read-only property" |
| Чи працює глибоко | Ні, лише верхній рівень (для глибокого захисту - DeepReadonly<T>) |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.