Я закінчив грати з декораторами і вирішив задокументувати те, що я зрозумів для тих, хто хоче цим скористатися, перш ніж вийде будь-яка документація. Будь ласка, не соромтесь редагувати це, якщо ви бачите помилки.
Загальні бали
- Декоратори викликаються при оголошенні класу, а не тоді, коли об'єкт інстанціюється.
- Для одного класу / властивості / методу / параметра можна встановити кілька декораторів.
- Декоратори не дозволяються на конструкторах.
Дійсний декоратор повинен бути:
- Відноситься до одного з видів декораторів (
ClassDecorator | PropertyDecorator | MethodDecorator | ParameterDecorator
).
- Поверніть значення (у випадку декораторів класу та декоратора методів), яке можна віднести до декорованого значення.
Довідково
Спосіб / формальний декоратор аксесуарів
Параметри реалізації:
target
: Прототип класу ( Object
).
propertyKey
: Назва методу ( string
| symbol
).
descriptor
: A TypedPropertyDescriptor
- Якщо ви не знайомі з ключами дескриптора, я рекомендую прочитати про це в цій документації на Object.defineProperty
(це третій параметр).
Приклад - Без аргументів
Використання:
class MyClass {
@log
myMethod(arg: string) {
return "Message -- " + arg;
}
}
Впровадження:
function log(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
const originalMethod = descriptor.value; // save a reference to the original method
// NOTE: Do not use arrow syntax here. Use a function expression in
// order to use the correct value of `this` in this method (see notes below)
descriptor.value = function(...args: any[]) {
// pre
console.log("The method args are: " + JSON.stringify(args));
// run and store result
const result = originalMethod.apply(this, args);
// post
console.log("The return value is: " + result);
// return the result of the original method (or modify it before returning)
return result;
};
return descriptor;
}
Вхід:
new MyClass().myMethod("testing");
Вихід:
Аргументи методу: ["тестування"]
Повертається значення: Тестування повідомлення
Примітки:
- Не використовуйте синтаксис стрілок під час встановлення значення дескриптора. У цьому випадку контекст
this
не буде екземпляром.
- Краще змінити оригінальний дескриптор, ніж перезаписати поточний, повернувши новий дескриптор. Це дозволяє використовувати кілька декораторів, які редагують дескриптор, не перезаписуючи те, що робив інший декоратор. Це дозволяє вам використовувати щось на кшталт
@enumerable(false)
і @log
одночасно (Приклад: Погано проти Хорошого )
- Корисно : Аргумент типу
TypedPropertyDescriptor
може бути використаний для обмеження того, який підпис методу ( Приклад методу ) або підпису аксесуара ( Приклад аксесуара ) може бути розміщений декоратором.
Приклад - з аргументами (фабрика декораторів)
Використовуючи аргументи, ви повинні оголосити функцію з параметрами декоратора, а потім повернути функцію з підписом прикладу без аргументів.
class MyClass {
@enumerable(false)
get prop() {
return true;
}
}
function enumerable(isEnumerable: boolean) {
return (target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => {
descriptor.enumerable = isEnumerable;
return descriptor;
};
}
Декоратор статичного методу
Подібний до декоратора методу з деякими відмінностями:
- Його
target
параметр - сама функція конструктора, а не прототип.
- Дескриптор визначається функцією конструктора, а не прототипом.
Декоратор класу
@isTestable
class MyClass {}
Параметр реалізації:
target
: Клас декоратора оголошено на ( TFunction extends Function
).
Приклад використання : Використання метаданих api для зберігання інформації про клас.
Декоратор власності
class MyClass {
@serialize
name: string;
}
Параметри реалізації:
target
: Прототип класу ( Object
).
propertyKey
: Назва об’єкта ( string
| symbol
).
Приклад використання : Створення @serialize("serializedName")
декоратора та додавання імені властивості до списку властивостей для серіалізації.
Параметр Декоратор
class MyClass {
myMethod(@myDecorator myParameter: string) {}
}
Параметри реалізації:
target
: Прототип класу ( Function
- здається, Function
він більше не працює. Ви повинні використовувати any
або Object
тут зараз для використання декоратора в будь-якому класі. Або вкажіть типи класів, які ви хочете обмежити)
propertyKey
: Назва методу ( string
| symbol
).
parameterIndex
: Індекс параметра у списку параметрів функції ( number
).
Простий приклад
Детальний приклад
@Injectable