← Назад к вопросам
Что такое декоратор?
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 - Производительность может быть ниже
- Усложняет отладку
Декораторы — это мощный инструмент для добавления функционала к существующему коду без его модификации, что делает код более гибким и поддерживаемым.