Как можно написать декоратор, который бы указанную функцию оборачивал бы в определённый код?

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

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

function wrapperDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value; // сохраняем оригинальную функцию
  
  descriptor.value = function(...args: any[]) { // переопределяем дескриптор функции
    console.log('Начало обертки'); // код, который будет добавлен перед вызовом функции
    const result = originalMethod.apply(this, args); // вызываем оригинальную функцию
    console.log('Конец обертки'); // код, который будет добавлен после вызова функции
    return result; // возвращаем результат работы функции
  };
  
  return descriptor; // возвращаем измененный дескриптор
}

Пояснение к коду:

- Декоратор wrapperDecorator принимает три параметра: target (целевой объект), propertyKey (имя свойства или метода), и descriptor (дескриптор свойства или метода).
- Внутри декоратора мы сохраняем оригинальную функцию в переменную originalMethod.
- Затем мы переопределяем дескриптор функции, добавляя новую функциональность.
- В данном случае, перед вызовом функции мы выводим в консоль сообщение 'Начало обертки', а после вызова функции - 'Конец обертки'.
- Затем мы вызываем оригинальную функцию с помощью originalMethod.apply(this, args), передавая ей все переданные аргументы.
- И, наконец, мы возвращаем результат работы функции и измененный дескриптор.
- Для того, чтобы декоратор работал, его нужно применить непосредственно к целевой функции или методу.

Пример использования декоратора:

class Example {
  @wrapperDecorator
  greet(name: string) {
    console.log(`Привет, ${name}!`);
  }
}

const example = new Example();
example.greet('Вася');

Вывод в консоль:

Начало обертки
Привет, Вася!
Конец обертки

Таким образом, декоратор wrapperDecorator добавляет код до и после вызова функции greet. Вы можете настраивать декоратор, добавляя или изменяя код внутри него, чтобы соответствовать вашим потребностям.