/
decorator-utils.ts
44 lines (39 loc) · 1.53 KB
/
decorator-utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
export type PropertyOrGetterDescriptor = (
target: Object,
propertyName: string | symbol,
propertyDescriptor?: PropertyDescriptor,
) => void;
export interface ParameterizedPropertyDecorator<T> {
(options: T): PropertyOrGetterDescriptor;
(target: Object, propertyName: string | symbol, propertyDescriptor?: PropertyDescriptor): void;
}
/**
* Makes a decorator that can optionally receive a parameter
*
* @param defaultValue The value to use if no parameter is provided.
* @param callback The callback that will be executed once the decorator is applied.
*/
export function makeParameterizedPropertyDecorator<T>(
defaultValue: T,
callback: (
option: T,
target: Object,
propertyName: string | symbol,
propertyDescriptor: PropertyDescriptor | undefined,
) => void,
): ParameterizedPropertyDecorator<T> {
return function decorator(...args: [options: T] | Parameters<PropertyOrGetterDescriptor>) {
if (args.length === 1) {
return function parameterizedDecorator(
target: Object,
propertyName: string | symbol,
propertyDescriptor?: PropertyDescriptor | undefined,
) {
callback(args[0], target, propertyName, propertyDescriptor ?? Object.getOwnPropertyDescriptor(target, propertyName));
};
}
callback(defaultValue, args[0], args[1], args[2] ?? Object.getOwnPropertyDescriptor(args[0], args[1]));
// this method only returns something if args.length === 1, but typescript doesn't understand it
return undefined as unknown as PropertyOrGetterDescriptor;
};
}