Readonly свойства
readonlyв TypeScript — модификатор свойства или элемента кортежа, запрещающий переприсвоение после инициализации на уровне системы типов.
Зачем нужно
readonly защищает от случайных мутаций объектов и массивов на этапе компиляции. Это особенно важно в функциональном стиле, при работе с иммутабельным state (Redux), и для защиты конфигурационных объектов. В отличие от const, readonly работает на уровне свойств, а не переменных.
Где используется
- Иммутабельные value objects и DTO
- Конфигурационные объекты
readonlyмассивы в функциях (принимать без мутации)- Parameter properties в конструкторах
- Защита полей класса от изменения снаружи
Основной контент
readonly в интерфейсах и type alias
interface Point {
readonly x: number;
readonly y: number;
}
const p: Point = { x: 0, y: 0 };
// p.x = 1; // Error: Cannot assign to 'x' because it is a read-only property
// p.y = 2; // Error
// Но объект можно переприсвоить (readonly не влияет на переменную)
let point: Point = { x: 0, y: 0 };
point = { x: 1, y: 2 }; // OK — переприсвоение переменной
readonly в классах
class Circle {
readonly radius: number;
readonly center: Point;
constructor(radius: number, center: Point) {
this.radius = radius; // OK — в конструкторе
this.center = center;
}
scale(factor: number): Circle {
// this.radius *= factor; // Error — нельзя изменить readonly
return new Circle(this.radius * factor, this.center);
}
}
readonly массивы
// ReadonlyArray<T> или readonly T
function sum(numbers: readonly number): number {
// numbers.push(4); // Error — push не доступен
// numbers[0] = 10; // Error
return numbers.reduce((acc, n) => acc + n, 0);
}
const nums = [1, 2, 3];
sum(nums); // OK — number присваивается readonly number
const frozen: ReadonlyArray<string> = ["a", "b", "c"];
// frozen.push("d"); // Error
readonly кортежи
type Pair = readonly [number, string];
const p: Pair = [1, "hello"];
// p[0] = 2; // Error
// p.push(3); // Error
Разница const и readonly
const obj = { name: "Alice" };
obj.name = "Bob"; // OK — const запрещает переприсвоение переменной, не мутацию
const readonlyObj: { readonly name: string } = { name: "Alice" };
// readonlyObj.name = "Bob"; // Error — readonly запрещает мутацию свойства
Readonly утилитарный тип
interface Config {
host: string;
port: number;
}
// Все поля readonly
const config: Readonly<Config> = { host: "localhost", port: 3000 };
// config.host = "example.com"; // Error
Важно: readonly — только на уровне типов
// В рантайме readonly не защищает от мутации!
const obj = { x: 1 } as { readonly x: number };
(obj as { x: number }).x = 2; // Компилятор запретит без cast, но в JS это работает
// Для рантайм-защиты используйте Object.freeze:
const frozen = Object.freeze({ x: 1, y: 2 });
// frozen.x = 5; // TypeError в рантайме
Частые ошибки
- Думать что
readonly=const—constзапрещает переприсвоение переменной;readonlyзапрещает мутацию свойства. - Ожидать защиты вложенных объектов —
readonlyповерхностный; вложенные объекты можно мутировать. - Не использовать
readonlyдля параметров-массивов — безreadonly numberфункция может случайно мутировать входной массив. - Забывать что в рантайме readonly не работает — для реальной защиты нужен
Object.freeze.
Связанные темы
- Partial, Required, Readonly
- Parameter Properties
- interface -- объявление и использование
- Типизация объектов
- _MOC TypeScript