Gernar
Frontend DeveloperTypeScript

Интервью-вопрос

Что такое декоратор в TypeScript

Декоратор это синтаксис с @, который применяет функцию к объявлению и может добавить метаданные, обертку или инициализацию. На интервью важно не смешать modern и legacy-декораторы и не обещать автоматическое изменение типов.

Добавлен
Редакция

Подготовьте короткий ответ и пару деталей на случай уточняющих вопросов.

🐰0
🥚0

Мини-квиз

Проверка перед разбором

Несколько быстрых вопросов перед разбором. Так проще поймать места, которые только кажутся понятными.

Вопрос 1 из 60 правильно

Как лучше коротко объяснить, что такое декоратор?

Вы отвечаете на базовый вопрос и хотите сразу показать практический смысл.

Варианты ответа

Разбор

Разобраться, а не зазубрить

Дальше разбираем суть, типичные уточнения и места, где легко сказать лишнее или перепутать термины.

Базовая идея

Декоратор отвечает на вопрос, что сделать с объявлением, когда класс или его элемент определяется. В коде он выглядит как @something перед классом, методом, полем или аксессором.

На интервью важно объяснить не только синтаксис, но и смысл. Декоратор держит сквозную или декларативную логику рядом с объявлением. Например, фреймворк читает настройки компонента, библиотека состояния помечает поле как observable, а ваш код оборачивает метод логированием.

Хорошая короткая формулировка:

Декоратор это функция, примененная к объявлению через синтаксис @. Она может добавить метаданные или изменить поведение элемента. При этом она не делает TypeScript-тип магически умнее и не работает одинаково во всех режимах TypeScript.

Modern и legacy нужно разделять

В TypeScript не стоит говорить о декораторах как об одной неизменной механике. В проектах встречаются две модели.

Legacy-декораторы появились в TypeScript давно и включались через experimentalDecorators. У них знакомые сигнатуры вида target, propertyKey, descriptor. Еще у них есть параметрные декораторы. Такой код часто встречается в старых проектах и во фреймворках, которые исторически строились вокруг этой модели.

Современные decorators ближе к ECMAScript-предложению. У них другая сигнатура. Декоратор получает значение и context, может вернуть замену или добавить инициализацию. Параметрных декораторов в этой стандартной модели нет.

Практический вывод простой. Если вы приводите пример, назовите модель. Так вы не смешаете несовместимые сигнатуры.

Как выбрать формулировку ответа

1Вопрос про Angular, Lit, MobX или другой фреймворк?
Скажите, что декоратор описывает контракт для фреймворка. Это может быть компонент, сервис, observable-поле или настройка элемента.
2Вопрос про собственный декоратор метода?
Объясните обертку. Она должна сохранить <code>this</code>, аргументы, результат и обработку ошибок.
3Вопрос про совместимость и конфиг TypeScript?
Разведите modern decorators и legacy experimentalDecorators. Не смешивайте их сигнатуры.
4Нужно предложить решение для обычного React-кода?
Сначала предложите явную функцию, хук или компонент-обертку. Декоратор берите только если он уже принят в архитектуре.
5Вопрос про сетевой метод или browser-only API?
Скажите, что декоратор не должен делать side effect при загрузке модуля. Запрос, чтение DOM и работу с <code>window</code> держите внутри явного вызова и защищайте для SSR.

Пример с методом

Этот пример показывает современный декоратор метода. Он не просто помечает метод. Он возвращает обертку, которая вызывается вместо исходного метода.

function logged<This, Args extends unknown[], Return>(
  originalMethod: (this: This, ...args: Args) => Return,
  context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
  const methodName = String(context.name);

  return function (this: This, ...args: Args): Return {
    console.log(`${methodName} called`, { argsCount: args.length });
    return originalMethod.apply(this, args);
  };
}

class ApiClient {
  @logged
  async loadUser(id: string, signal?: AbortSignal) {
    const response = await fetch(`/api/users/${encodeURIComponent(id)}`, { signal });

    if (!response.ok) {
      throw new Error(`Failed to load user: ${response.status}`);
    }

    return response.json() as Promise<unknown>;
  }
}

В ответе проговорите детали. Обертка сохраняет this, передает аргументы и возвращает результат. Если забыть return, вызывающий код получит undefined вместо Promise. UI может навсегда остаться в loading, потому что обработчик ждет результат запроса. Если потерять this, метод может упасть при обращении к полям экземпляра.

Пример с fetch безопаснее держать внутри исходного метода, а не внутри самого декоратора. Метод принимает AbortSignal, проверяет response.ok и кодирует id для URL. Так вызывающий React-компонент может отменить устаревший запрос в cleanup и не перезаписать экран данными от старого ответа.

Еще один практический риск. Не логируйте токены, пароли и персональные данные в таком декораторе. Он может начать писать в консоль или аналитику аргументы всех методов подряд. Поэтому в примере логируется только количество аргументов, а не их значения.

Где это встречается во фронтенде

Самый понятный пример для frontend-разработчика это фреймворки и библиотеки, где декоратор является частью публичного API.

В Angular @Component связывает класс с настройками компонента. Это селектор, шаблон, стили и зависимости. В библиотеках состояния декораторы могут помечать observable-поля или computed-значения. В web component библиотеках они могут связывать свойства класса с атрибутами или реактивным обновлением.

Не говорите так, будто декораторы нужны везде. В React-коде чаще используют хуки, функции, компоненты-обертки и явную композицию. Декоратор оправдан, если он уже является частью архитектуры, упрощает повторяющийся контракт и не прячет важную бизнес-логику.

Какие риски назвать на практике

Фреймворк@Component

Декоратор хранит настройки класса для компилятора или рантайма. При рефакторинге легко удалить метаданные и сломать регистрацию компонента.

Методлогирование

Декоратор может вернуть обертку вокруг метода. Риск в том, что вы потеряете <code>this</code>, забудете вернуть <code>Promise</code>, проглотите ошибку или не передадите <code>AbortSignal</code>. В UI это дает зависший loading или race condition.

Поле или accessorинициализация

Декоратор может влиять на инициализацию или доступ к значению. Риск в том, что вы рассчитываете на порядок, который отличается от обычного присваивания, или читаете browser-only API во время загрузки модуля.

Параметрlegacy only

В старой модели параметрные декораторы встречаются. В современной стандартной модели их нет. Поэтому не обещайте переносимость такого кода без проверки режима.

Что декоратор не делает автоматически

Декоратор не является магическим способом сделать код типобезопасным. Если он добавляет новое поле в экземпляр или меняет форму класса, TypeScript может не знать об этом без отдельной типизации.

Плохая формулировка:

Декоратор добавит поле, и TypeScript сам поймет, что оно есть.

Лучше сказать так:

Декоратор может добавить поведение в рантайме, но типовой контракт нужно описать отдельно. Иначе вы получите расхождение между тем, что реально есть в объекте, и тем, что видит компилятор.

Это важный практический вывод. Расхождение типов и рантайма приводит к хрупким тестам, неожиданным undefined и ошибкам при рефакторинге.

Как отвечать коротко на интервью

Если нужен ответ на 30 секунд, можно сказать:

Декоратор в TypeScript это функция, которую применяют к объявлению через @. Она может добавить метаданные, зарегистрировать класс во фреймворке или вернуть обертку для метода или поля. Например, @Component в Angular описывает класс компонента для фреймворка. При этом важно различать modern decorators и legacy experimental decorators, потому что у них разные сигнатуры и поддержка параметров.

Если вас просят привести пример, выбирайте простой метод-декоратор или фреймворковый пример. Не уходите в сложную метапрограмму, если не можете уверенно объяснить порядок выполнения и типовые ограничения.

Частые ошибки

Где обычно ошибаются

Проверьте формулировки, которые звучат уверенно, но на интервью быстро выдают пробелы.

  1. 1

    Смешивать modern и legacy-декораторы

    У старых и современных декораторов разные сигнатуры и разные возможности. Если вы приводите legacy-пример с target, propertyKey и descriptor, не называйте его универсальным для любого TypeScript-проекта. Без уточнения версии и режима ответ звучит неточно.
  2. 2

    Говорить, что декоратор всегда меняет тип

    Декоратор может добавить поведение в рантайме, но TypeScript не обязан автоматически увидеть новые свойства. Если вы обещаете безопасность типов без отдельной типизации, ответ звучит рискованно. Лучше сказать, что runtime и static types нужно согласовать явно.
  3. 3

    Писать обертку метода без сохранения контракта

    Если обертка не передает this, не возвращает результат или меняет обработку ошибок, UI может получить неверное состояние или зависший loading. Безопасный вариант вызывает исходный метод через apply или корректный call и возвращает его результат.
  4. 4

    Запускать side effect во время применения декоратора

    Декоратор выполняется при загрузке модуля. Если внутри него сразу вызвать fetch, прочитать localStorage или обратиться к window, можно получить лишний запрос, падение на SSR или hydration mismatch. Безопаснее оставить side effect внутри явного метода, эффекта React или обработчика события. Там есть cleanup, AbortController и обработка ошибок.
  5. 5

    Использовать декоратор там, где хватит явной функции

    Декоратор скрывает часть логики за синтаксисом @. В небольшом React-коде это часто ухудшает читаемость и усложняет сборку. Выбирайте декоратор только там, где он является частью архитектуры или API фреймворка.
  6. 6

    Путать метаданные с выполнением бизнес-логики

    Декоратор может зарегистрировать метаданные, но это не значит, что он сам валидирует форму или защищает endpoint при каждом действии пользователя. Если нужна проверка на submit, ее все равно нужно выполнить в явном месте. Иначе появляется ложное чувство безопасности.

Follow-up

Что могут спросить дальше

Короткие ответы на вопросы, которыми проверяют нюансы TypeScript-декораторов и их применение во фронтенде.

Живые ответы

Видео с похожим вопросом

Если найдем публичные интервью с таким вопросом, добавим их сюда. Их удобно смотреть после теории, чтобы свериться с живыми ответами.

Пока видео нет. Когда появятся подходящие публичные интервью, добавим их в этот блок, чтобы можно было сравнить разбор с тем, как отвечают реальные кандидаты.

Содержание