Опциональные и readonly свойства

Тонкая настройка свойств: что может отсутствовать и что нельзя менять.

Модификатор ? делает свойство необязательным, readonly — запрещает его изменять после создания.

Опциональные свойства

Не у всех объектов заполнены все поля. Необязательное свойство помечают ? — его можно не указывать:

interface User {
  name: string;
  age: number;
  phone?: string; // может быть, а может не быть
}

const a: User = { name: "Аня", age: 30 };               // ок, без phone
const b: User = { name: "Боря", age: 25, phone: "555" }; // тоже ок

Тип такого свойства внутри — string | undefined. Поэтому перед использованием его нужно проверить, иначе компилятор не пропустит:

function callUser(u: User) {
  // u.phone.length; // Ошибка: 'u.phone' is possibly 'undefined'.
  if (u.phone) {
    console.log("Звоним на " + u.phone);
  }
}

Это защищает от обращения к отсутствующему полю — частого источника ошибок при работе с данными API, где поля приходят не всегда.

readonly свойства

Модификатор readonly делает свойство неизменяемым: его задают при создании, но переписать потом нельзя.

interface Account {
  readonly id: number; // выдаётся один раз
  balance: number;     // меняется
}

const acc: Account = { id: 1, balance: 100 };
acc.balance = 150;  // ок
acc.id = 2;         // Ошибка: Cannot assign to 'id' because it is a read-only property.

Это защита на этапе компиляции: случайно изменить идентификатор, дату создания или другое неизменяемое поле не получится. Баг «кто-то перезаписал id» становится невозможен.

Важно: readonly — только для проверки типов

Помните: readonly существует лишь во время компиляции. В готовом JavaScript никакой защиты не остаётся — это не Object.freeze. Польза в том, что компилятор не даст написать изменяющий код, и ошибка не доедет до рантайма.

readonly-массивы

Массив тоже можно сделать неизменяемым — тогда у него пропадают мутирующие методы (push, pop):

const days: readonly string[] = ["Пн", "Вт", "Ср"];
days.push("Чт"); // Ошибка: Property 'push' does not exist on type 'readonly string[]'.

Это удобно для констант и данных, которые не должны меняться после инициализации.

Памятка

МодификаторСмысл
phone?: stringсвойства может не быть; тип string | undefined
readonly id: numberзадаётся при создании, менять нельзя
readonly string[]массив без мутирующих методов

Итог

  • ? делает свойство необязательным; перед использованием его проверяют на undefined.
  • readonly запрещает изменять свойство после создания — защита от случайной перезаписи.
  • Оба модификатора работают только на этапе компиляции, без накладных расходов в рантайме.
Проверьте себя
1. Какой тип имеет опциональное свойство phone?: string внутри объекта?
Astring
Bstring | undefined
Cany
Dreadonly string
2. Что делает модификатор readonly у свойства?
AСкрывает свойство от внешнего кода
BЗапрещает изменять свойство после создания объекта
CДелает свойство необязательным
DШифрует значение свойства
3. Действует ли readonly во время выполнения скомпилированного JavaScript?
AДа, это аналог Object.freeze
BНет, readonly проверяется только компилятором и исчезает в рантайме
CДа, но только для массивов
DТолько если включён strict
Поддержать проект