Как использовать декораторы в TypeScript

Декораторы в TypeScript — это мощная функция, которая позволяет разработчикам добавлять дополнительную функциональность к классам, методам, свойствам и параметрам. Они предоставляют способ изменять поведение существующего кода, не меняя его фактическую структуру. В этом руководстве объясняется, как использовать декораторы в TypeScript, с простыми для понимания примерами.

Кто такие декораторы?

Декораторы — это специальные функции, которые можно применять к классам, методам, свойствам или параметрам. Они вызываются во время выполнения и позволяют разработчикам аннотировать и изменять код декларативным способом. Чтобы включить декораторы в проекте TypeScript, флаг experimentalDecorators должен быть установлен в значение true в файле tsconfig.json.

Включение декораторов в TypeScript

Для использования декораторов компилятор TypeScript должен быть настроен на их распознавание. Это можно сделать, установив флаг experimentalDecorators на true в файле tsconfig.json.

{
  "compilerOptions": {
    "target": "ES6",
    "experimentalDecorators": true
  }
}

После включения декораторов их можно использовать на протяжении всего проекта.

Создание декоратора класса

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

function LogClass(target: Function) {
  console.log(`Class ${target.name} is created.`);
}

@LogClass
class Person {
  constructor(public name: string) {}
}

const person = new Person('Alice');

В этом примере декоратор LogClass регистрирует сообщение при создании класса Person. Декоратор определяется как функция, которая принимает один аргумент: конструктор декорируемого класса.

Метод Декораторы

Декораторы методов применяются к методам внутри класса. Они позволяют разработчикам перехватывать вызовы методов, изменять их поведение или выполнять дополнительные операции до или после выполнения метода.

function LogMethod(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Method ${propertyKey} is called with arguments: ${args}`);
    return originalMethod.apply(this, args);
  };

  return descriptor;
}

class Calculator {
  @LogMethod
  add(a: number, b: number): number {
    return a + b;
  }
}

const calc = new Calculator();
calc.add(2, 3);

Здесь декоратор LogMethod регистрирует имя метода и его аргументы всякий раз, когда вызывается метод add. Он оборачивает исходный метод в новую функцию, которая выполняет регистрацию перед делегированием исходному методу.

Декораторы недвижимости

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

function ReadOnly(target: Object, propertyKey: string) {
  Object.defineProperty(target, propertyKey, {
    writable: false
  });
}

class Book {
  @ReadOnly
  title: string = 'TypeScript Guide';
}

const myBook = new Book();
myBook.title = 'New Title'; // This will cause an error in strict mode

В этом примере декоратор ReadOnly применяется к свойству title класса Book, делая его доступным только для чтения путем установки writable в значение false.

Декораторы параметров

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

function LogParameter(target: Object, propertyKey: string, parameterIndex: number) {
  console.log(`Parameter in position ${parameterIndex} at ${propertyKey} method is decorated.`);
}

class UserService {
  greet(@LogParameter message: string): void {
    console.log(message);
  }
}

const userService = new UserService();
userService.greet('Hello, TypeScript!');

В этом примере декоратор LogParameter применяется к параметру message метода greet в классе UserService. Декоратор регистрирует информацию о декорируемом параметре.

Заключение

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