В TypeScript модификаторы доступа используются для ограничения области видимости свойств и методов в классах:
class Animal { public name: string; private age: number; protected kind: string; constructor(name: string, age: number, kind: string) { this.name = name; this.age = age; this.kind = kind; } } class Dog extends Animal { bark() { console.log(this.kind); // OK: protected // console.log(this.age); // Ошибка: private не видно в наследнике } } const dog = new Dog('Шарик', 5, 'млекопитающее'); console.log(dog.name); // OK // console.log(dog.kind); // Ошибка: protected // console.log(dog.age); // Ошибка: private
#field, но это уже спецификация JS, и компилируется иначе.Вопрос: Можно ли получить доступ к private свойству класса TypeScript после компиляции в JavaScript?
Ответ: Да, так как private (и protected) — это проверка TypeScript на этапе компиляции, после компиляции в ES5 или ES6 приватность не сохраняется, свойства остаются в объекте и доступны через обращение по имени свойства (например, через object['privateProp']).
// JS код после компиляции function Animal(name, age, kind) { this.name = name; this.age = age; this.kind = kind; } var dog = new Animal('Шарик', 5, 'млекопитающее'); console.log(dog['age']); // 5 — доступа нет только на уровне TS!
История
В крупном проекте разработчик рассчитывал на факт недоступности private-полей в рантайме. В результате при передачи объекта сериализацией (JSON.stringify) в логи случайно попали конфиденциальные данные, так как типизация TS не защитила от реального доступа к полям.
История
В проекте был реализован механизм "расширения" экземпляров классов через динамическое добавление свойств. Динамически добавленные свойства перезаписывали private-названия, и их случайно модифицировали внешний код. Ошибка была обнаружена только на production, причем приватность не была обеспечена.
История
При миграции с JavaScript на TypeScript команда стала использовать protected, считая, что это защищает от использования полей вне дочерних классов. Но программист через
Object.assignпо ошибке перезаписал protected-поле в рантайме и получил трудноотлавливаемый баг. Это стало возможным, потому что runtime-инкапсуляции не было.