Что такое `readonly` в TypeScript?
readonly — модификатор TypeScript, который запрещает переприсваивание свойства объекта или элемента массива после инициализации. Это проверка на уровне типов: в рантайме JavaScript не накладывает никаких ограничений.Что такое readonly
readonly — ключевое слово TypeScript, которое помечает свойство объекта или элемент массива как доступный только для чтения. После инициализации значение нельзя переприсвоить — компилятор выдаст ошибку.
interface User {
readonly id: number;
name: string;
}
const user: User = { id: 1, name: 'Иван' };
user.name = 'Пётр'; // OK
user.id = 2; // Ошибка: Cannot assign to 'id' because it is a read-only property
Применение в классах
readonly можно использовать в свойствах класса. Присваивание разрешено только в объявлении или в конструкторе.
class Order {
readonly createdAt: Date;
constructor() {
this.createdAt = new Date(); // OK — присваивание в конструкторе разрешено
}
reset() {
this.createdAt = new Date(); // Ошибка: свойство readonly
}
}
ReadonlyArray и readonly для массивов
Для массивов readonly запрещает мутирующие методы (push, pop, splice и т.д.).
const nums: readonly number[] = [1, 2, 3];
nums.push(4); // Ошибка: Property 'push' does not exist on type 'readonly number[]'
nums[0] = 99; // Ошибка: Index signature in type 'readonly number[]' only permits reading
Утилитный тип Readonly<T>
TypeScript предоставляет встроенный mapped type Readonly<T>, который делает все свойства типа T доступными только для чтения.
interface Config {
host: string;
port: number;
}
const config: Readonly<Config> = {
host: 'localhost',
port: 3000,
};
config.host = 'prod.example.com'; // Ошибка: свойство read-only
Важное ограничение: только поверхностная защита
readonly действует не рекурсивно — он защищает только прямое переприсваивание ссылки, но не вложенные объекты.
interface Company {
readonly address: { city: string };
}
const company: Company = { address: { city: 'Москва' } };
company.address = { city: 'Питер' }; // Ошибка
company.address.city = 'Питер'; // OK — TypeScript это разрешает
Для глубокой неизменяемости используют рекурсивные утилитные типы или библиотеки типа type-fest.
readonly — только типовая проверка
Важно понимать: readonly существует только на уровне TypeScript. После компиляции в JavaScript никаких ограничений на изменение объекта нет. Если нужна реальная неизменяемость в рантайме — используйте Object.freeze().
Что хочет услышать интервьюер
Кандидат чётко объясняет, что `readonly` — это ограничение на уровне типов, а не рантайма
Знает, где применяется: свойства интерфейсов/типов, свойства классов, массивы
Понимает разницу между `readonly`-свойством и `const`-переменной
Упоминает утилитный тип `Readonly<T>` как удобный способ сделать все поля readonly
Осознаёт, что защита поверхностная — вложенные объекты могут мутироваться
Пример: readonly в интерфейсе
interface Product {
readonly id: string; // нельзя изменить после создания
name: string;
price: number;
}
const product: Product = { id: 'abc-123', name: 'Курс TypeScript', price: 2990 };
product.name = 'Курс React'; // OK
product.id = 'xyz-456'; // Ошибка: Cannot assign to 'id' because it is a read-only property
Пример: Readonly<T> — утилитный тип
interface Settings {
theme: 'light' | 'dark';
language: string;
}
// Все свойства становятся readonly
function applySettings(settings: Readonly<Settings>) {
settings.theme = 'light'; // Ошибка внутри функции — нельзя менять
console.log(settings.theme);
}
Пример: readonly в классе
class Invoice {
readonly number: string;
readonly createdAt: Date;
constructor(number: string) {
this.number = number; // OK — присваивание в конструкторе разрешено
this.createdAt = new Date();
}
updateNumber(n: string) {
this.number = n; // Ошибка: свойство readonly нельзя менять вне конструктора
}
}
Пример: readonly массив
const allowedRoles: readonly string[] = ['admin', 'editor', 'viewer'];
allowedRoles.push('guest'); // Ошибка: push отсутствует в readonly string[]
console.log(allowedRoles[0]); // OK — чтение разрешено
Типичные ошибки
Путают `readonly` и `const`: `const` запрещает переприсваивание переменной, `readonly` — свойства объекта
Считают, что `readonly` защищает вложенные объекты — на самом деле только верхний уровень
Думают, что `readonly` влияет на поведение в рантайме JavaScript — это чисто TypeScript-конструкция
Не знают об утилитном типе `Readonly<T>` и пишут `readonly` для каждого поля вручную
Не понимают, что в конструкторе класса `readonly`-свойство можно присваивать — это разрешено


