Почему в не определяется Descriptor, определяющий свойства метода класса в декораторе TypeScript?
Пытаюсь изучить Декораторы методов в TypeScript. В примере попоробую декорировать метод внутри класса getUserInDataBase() декоратором @Log и descriptor определяется как undefined, то есть не видит реализацию метода getUserInDataBase() я уже что только не пробовал.
interface IUserService {
users: number;
getUserInDataBase(): number;
}
class UserService implements IUserService {
users: number = 1000;
@Log
getUserInDataBase(): number {
return this.users;
}
}
function Log(
target: Object,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<(...args: any[]) => any>
): TypedPropertyDescriptor<(...args: any[]) => any> | void {
console.log(descriptor);
const oldMethod = descriptor.value
descriptor.value = () => {
console.log("Some text");
return oldMethod()
};
}
console.log(new UserService().getUserInDataBase());
При компиляции получаю ошибки:
decoratorMethod.ts:9:3 - error TS1241: Unable to resolve signature of method decorator when called as an expression.
The runtime will invoke the decorator with 2 arguments, but the decorator expects 3.
9 @Log
~~~~
decoratorMethod.ts:18:3
18 descriptor: TypedPropertyDescriptor<(...args: any[]) => any>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An argument for 'descriptor' was not provided.
decoratorMethod.ts:9:4 - error TS1270: Decorator function return type 'void | TypedPropertyDescriptor<(...args: any[]) => any>' is not assignable to type 'void | (() => number)'.
Type 'TypedPropertyDescriptor<(...args: any[]) => any>' is not assignable to type 'void | (() => number)'.
9 @Log
~~~
Found 2 errors in the same file, starting at: decoratorMethod.ts:9
А при запуске скомпилированого _.js получаю:
undefined
D:\JS\TS\decorators\decoratorMethod.js:57
descriptor.value = function () {
^
TypeError: Cannot set properties of undefined (setting 'value')
at Log (D:\JS\TS\decorators\decoratorMethod.js:57:22)
at __esDecorate (D:\JS\TS\decorators\decoratorMethod.js:19:40)
at D:\JS\TS\decorators\decoratorMethod.js:51:13
at D:\JS\TS\decorators\decoratorMethod.js:52:11
at Object.<anonymous> (D:\JS\TS\decorators\decoratorMethod.js:54:2)
at Module._compile (node:internal/modules/cjs/loader:1159:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
at Module.load (node:internal/modules/cjs/loader:1037:32)
at Module._load (node:internal/modules/cjs/loader:878:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
Node.js v18.12.0
При этом в настройках tsconfig
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
}
Ответы (1 шт):
Автор решения: AgentIvan
→ Ссылка
для TS > 5.0 :
{
"experimentalDecorators": false,
}
и тогда немножко иные параметры декоратора
А при включенных экспериментальных декораторах:
{
"experimentalDecorators": true,
}
interface IUserService {
users: number;
get UserInDataBase(): number;
}
class UserService implements IUserService {
users: number = 1000;
@Log
get UserInDataBase(): number {
return this.users;
}
}
function Log<R extends {}, P>(
target: R,
propertyKey: keyof R,
descriptor: TypedPropertyDescriptor<P>
): TypedPropertyDescriptor<P> | void {
console.log(descriptor);
const oldAccessor = descriptor.get;
if (oldAccessor === undefined) throw "Decorator is only allowed on getters";
descriptor.get = function (this: R) {
// @ts-ignore
console.log(`decorating ${propertyKey}`);
return oldAccessor.call(this);
};
}
console.log(new UserService().UserInDataBase);