Геттеры и сеттеры в TypeScript: полный разбор с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Get и Set в TypeScript: магия аксессоров без боли

Вы когда-нибудь писали класс на TypeScript и думали: «Вот бы сделать свойство умным, чтобы при чтении оно что-то вычисляло, а при записи — проверяло данные»? Знакомьтесь — геттеры (get) и сеттеры (set). Это не просто синтаксический сахар, а мощный инструмент для контроля доступа к данным.

Если вы уже сталкивались с этой темой на Stack Overflow, то знаете: вопрос «get and set in TypeScript» собирает тысячи просмотров. Люди путаются, когда применять аксессоры, а когда — обычные методы. В этой статье мы разложим всё по полочкам: от базы до хитрых нюансов.

Готовы? Поехали!

Что такое get и set в TypeScript?

Геттер — это метод, который вызывается при чтении свойства. Сеттер — метод, вызываемый при присвоении значения. Вместе они образуют аксессоры (accessors). Выглядит это так, будто вы работаете с обычным полем, но под капотом — логика.

Вот минимальный пример:

class User {
  private _name: string = '';

  get name(): string {
    return this._name;
  }

  set name(value: string) {
    if (value.length > 0) {
      this._name = value;
    } else {
      console.log('Имя не может быть пустым');
    }
  }
}

const user = new User();
user.name = 'Анна'; // вызывается set
console.log(user.name); // вызывается get → 'Анна'
user.name = ''; // попытка установить пустое имя → сообщение в консоли

Обратите внимание: свойство _name с префиксом _ — это приватное поле. Прямой доступ к нему извне невозможен. Вместо этого мы используем публичный аксессор name.

Зачем нужны геттеры и сеттеры? 3 главные причины

1. Валидация данных

Сеттер — идеальное место для проверки входных значений. Вы можете отсечь некорректные данные до того, как они попадут в объект.

class Temperature {
  private _celsius: number = 0;

  get celsius(): number {
    return this._celsius;
  }

  set celsius(value: number) {
    if (value < -273.15) {
      throw new Error('Температура ниже абсолютного нуля невозможна');
    }
    this._celsius = value;
  }
}

2. Вычисляемые свойства

Геттер может возвращать не сохранённое значение, а результат вычислений на основе других данных.

class Rectangle {
  constructor(public width: number, public height: number) {}

  get area(): number {
    return this.width * this.height;
  }

  get perimeter(): number {
    return 2 * (this.width + this.height);
  }
}

const rect = new Rectangle(10, 5);
console.log(rect.area); // 50 — вычисляется на лету

3. Инкапсуляция и контроль доступа

Вы можете сделать свойство доступным только для чтения (только геттер) или только для записи (только сеттер). Это помогает соблюдать принципы ООП.

class Config {
  private _apiKey: string = 'secret123';

  get apiKey(): string {
    // Можно добавить логирование или проверку прав
    return this._apiKey;
  }
  // Сеттер не определён — свойство только для чтения
}

const config = new Config();
console.log(config.apiKey); // 'secret123'
// config.apiKey = 'newKey'; // Ошибка компиляции!

Частые вопросы про get и set в TypeScript

Давайте разберём то, что чаще всего спрашивают новички (и не только) на Stack Overflow и форумах.

Вопрос 1: Чем get/set отличаются от обычных методов?

Главное отличие — синтаксис вызова. Аксессоры выглядят как свойства: без круглых скобок. Это делает код чище и интуитивнее. Сравните:

// С методами
user.getName();
user.setName('Петр');

// С аксессорами
user.name;
user.name = 'Петр';

Второе отличие — аксессоры нельзя перегружать (overload). У каждого аксессора одна сигнатура.

Вопрос 2: Можно ли сделать геттер асинхронным?

Нет, геттеры и сеттеры обязаны быть синхронными. Если вам нужно асинхронное получение данных — используйте обычный метод.

class DataService {
  private _data: string = '';

  async fetchData(): Promise<string> {
    // Асинхронная логика
    return 'данные';
  }
}

Вопрос 3: Как работает сеттер с типами?

Тип параметра сеттера должен совпадать с типом возврата геттера (если геттер определён). TypeScript сам выводит тип, если вы явно его не указали.

class Score {
  private _value: number = 0;

  get value(): number {
    return this._value;
  }

  set value(v: number) {
    // v должен быть number — иначе ошибка компиляции
    this._value = v;
  }
}

Вопрос 4: Нужно ли всегда использовать приватное поле?

Да, если вы определяете аксессоры для свойства, которое хранит данные. Без приватного поля вы рискуете создать бесконечную рекурсию:

// ❌ Ошибка!
class BadExample {
  get name(): string {
    return this.name; // Бесконечный вызов геттера самого себя
  }

  set name(v: string) {
    this.name = v; // Бесконечный вызов сеттера
  }
}

Всегда храните данные в отдельном приватном поле с префиксом _.

Продвинутые техники: get и set в реальных проектах

Логирование изменений

С помощью сеттера можно отслеживать, когда и как меняются свойства:

class AuditUser {
  private _name: string = '';

  get name(): string {
    return this._name;
  }

  set name(value: string) {
    console.log(`[${new Date().toISOString()}] Имя изменено на "${value}"`);
    this._name = value;
  }
}

Ленивая инициализация (Lazy Loading)

Геттер может отложить создание «тяжёлого» объекта до первого обращения:

class HeavyService {
  private _data: string[] | null = null;

  get data(): string[] {
    if (!this._data) {
      console.log('Инициализация данных...');
      this._data = ['a', 'b', 'c']; // Дорогая операция
    }
    return this._data;
  }
}

const service = new HeavyService();
// Данные ещё не загружены
console.log(service.data); // Первый вызов — инициализация
console.log(service.data); // Второй вызов — просто возврат

Преобразование данных

Сеттер может автоматически преобразовывать входные значения:

class Formatter {
  private _text: string = '';

  get text(): string {
    return this._text.toUpperCase(); // Всегда возвращаем заглавными                

Блоги

Рекомендаций по книгам