← Назад к вопросам

Что такое декоратор?

2.0 Middle🔥 131 комментариев
#TypeScript#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Декораторы в JavaScript/TypeScript

Декоратор — это функция, которая принимает оригинальный объект (класс, метод, свойство) и возвращает модифицированную версию. Это паттерн, который позволяет добавлять новое поведение к существующему коду без его изменения (принцип Open/Closed из SOLID).

Концепция

Декоратор работает по принципу обертки (wrapper):

// Оригинальная функция
function greet(name: string) {
  return `Hello, ${name}`;
}

// Декоратор добавляет логирование
function withLogging(fn: Function) {
  return function(...args: any[]) {
    console.log(`Calling ${fn.name}`);
    return fn(...args);
  };
}

const greetWithLog = withLogging(greet);
greetWithLog("Alice"); // логирует перед вызовом

Декораторы в TypeScript

TypeScript имеет встроенную поддержку декораторов (экспериментальная функция):

// Включить в tsconfig.json:
// "experimentalDecorators": true

// Декоратор класса
function Entity(constructor: Function) {
  constructor.prototype.isEntity = true;
}

@Entity
class User {
  name: string = "John";
}

const user = new User();
console.log((user as any).isEntity); // true

Типы декораторов

1. Декораторы методов

function Memoize(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  const cache = new Map();

  descriptor.value = function(...args: any[]) {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = originalMethod.apply(this, args);
    cache.set(key, result);
    return result;
  };
  return descriptor;
}

class Calculator {
  @Memoize
  expensiveCalculation(a: number, b: number) {
    return a + b;
  }
}

2. Декораторы свойств

function Validate(target: any, propertyKey: string) {
  let value: any;
  const getter = () => value;
  const setter = (newVal: any) => {
    if (typeof newVal !== "string") {
      throw new Error(`${propertyKey} must be string`);
    }
    value = newVal;
  };
  Object.defineProperty(target, propertyKey, { get: getter, set: setter });
}

class User {
  @Validate
  name: string;
}

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

function Required(target: any, propertyKey: string, parameterIndex: number) {
  console.log(`Parameter ${parameterIndex} of ${propertyKey} is required`);
}

class Service {
  process(@Required value: string) {
    return value;
  }
}

Примеры использования

React: HOC как декоратор

function withRouter<P extends object>(Component: React.ComponentType<P>) {
  return (props: P) => {
    const router = useRouter();
    return <Component {...props} router={router} />;
  };
}

// Применение
const HomePage = withRouter(Home);

Логирование и отладка

function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  
  descriptor.value = function(...args: any[]) {
    console.log(`[${propertyKey}] called with`, args);
    const result = originalMethod.apply(this, args);
    console.log(`[${propertyKey}] returned`, result);
    return result;
  };
  return descriptor;
}

class UserService {
  @log
  getUser(id: number) {
    return { id, name: "Alice" };
  }
}

Валидация аргументов

function validate(schema: any) {
  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
    const originalMethod = descriptor.value;
    descriptor.value = function(...args: any[]) {
      // проверка аргументов по схеме
      return originalMethod.apply(this, args);
    };
    return descriptor;
  };
}

Преимущества

  • Переиспользуемость — один декоратор для многих классов
  • Чистота кода — разделяет основную логику от cross-cutting concerns
  • Читаемость — понятный синтаксис
  • Модульность — легко добавлять/убирать функционал

Важные замечания

  • В JavaScript это экспериментальная функция
  • Требует experimentalDecorators: true в TypeScript
  • Производительность может быть ниже
  • Усложняет отладку

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

Что такое декоратор? | PrepBro