Что такое `readonly` в TypeScript?

JuniorTypeScript · Frontend·Обновлено 1 августа 2026
Коротко
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`-свойство можно присваивать — это разрешено

Лучшие курсы по теме

изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Feature-Sliced Design

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.6
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее