Декораторы можно использовать для изменения поведения классов, при этом ещё больше пользы от них можно получить при их использовании с каким-либо фреймворком.
Например, если в вашем фреймворке есть методы, доступ к которым ограничен (скажем, они предназначены только для администратора), несложно будет написать декоратор метода @admin
, который будет запрещать доступ к соответствующим методам пользователям, не являющимся администраторами. Можно создать декоратор @owner
, который позволяет модифицировать объект только его владельцу. Вот как может выглядеть использование декораторов:
class CRUD {
get() { }
post() { }
@admin
delete() { }
@owner
put() { }
}
Декоратор
- это особый вид объявления, который позволяет вам изменять классы или члены классов сразу, помечая их аннотацией @<name>
. Каждый декоратор должен ссылаться на функцию, которая будет оцениваться во время выполнения.
Например, декоратор @sealed
будет соответствовать запечатанной функции. Все, что помечено @sealed
, будет использоваться для оценки запечатанной функции.
function sealed(target) {
// do something with 'target' ...
}
Их можно прикрепить к:
- Объявлениям классов
- Методам
- Свойствам-аксессорам
- Свойствам
- Параметрам
По умолчанию декораторы не включены. Чтобы включить их, вы должны отредактировать поле experimentalDecorators
в параметрах компилятора в файле tsconfig.json или в командной строке.
Примеры декораторов :
- Декоратор класса:
@logged
class MyClass {
// ...
}
function logged(target: Function) {
console.log(`Class ${target.name} created.`);
}
В этом примере декоратор класса logged
вызывается при создании класса MyClass
.
- Декоратор метода:
class MyClass {
@readonly
method() {
// ...
}
}
function readonly(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.writable = false;
}
В этом примере декоратор метода readonly
используется для установки свойстваwritable
объекта PropertyDescriptor
в false
, чтобы метод нельзя было изменить после определения.
- Декоратор свойства:
class MyClass {
@uppercase
name: string = "John Doe";
}
function uppercase(target: Object, propertyKey: string) {
let value = target[propertyKey];
const getter = function() {
return value.toUpperCase();
};
const setter = function(newValue) {
value = newValue.toUpperCase();
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
}
В этом примере декоратор свойства uppercase
используется для изменения значения свойства name
на UpperCase
.
- Декоратор параметра функции:
function validate(target: Object, propertyKey: string, parameterIndex: number) {
const originalMethod = target[propertyKey];
target[propertyKey] = function(...args: any[]) {
const arg = args[parameterIndex];
if (!arg) {
throw new Error(`Parameter ${parameterIndex} is required.`);
}
return originalMethod.apply(this, args);
};
}
class MyClass {
method(@validate arg: string) {
// ...
}
}
В этом примере декоратор параметра функции validate
используется для проверки наличия аргумента arg
при вызове метода method
. Если аргумент не передан, генерируется исключение.