2

Based on this answer, I tried to implement a function from another service inside a decorator.

Here is my attempt:

export function ClearCache() {
  const injectCacheService = Inject(CacheService);

  return (target: any, _: string, propertyDescriptor: PropertyDescriptor) => {
    injectCacheService(target, 'service'); // this is the same as using constructor(private readonly logger: LoggerService) in a class

    //get original method
    const originalMethod = propertyDescriptor.value;

    //redefine descriptor value within own function block
    propertyDescriptor.value = async function (...args: any[]) {
      try {
        console.log(this);
        const service: CacheService = this.service;
        service.clearCacheById(args[1]);

        return await originalMethod.apply(this, args);
      } catch (error) {
        console.error(error);
      }
    };
  };
}

But I got Property 'service' does not exist on type 'PropertyDescriptor'.ts(2339)

Any idea on what part I am missing?

Update:

tsconfig.json has "strict":true. If it is enabled, then "this" would be strictly use the PropertyDescriptor interface.

Fixed the issue by changing "strict": false in the tsconfig.json.

How to reproduce?

  • Use "strict":true on tsconfig.json
hikvineh
  • 150
  • 1
  • 10
  • I'd say that `PropertyDescriptor` is too generic so typescript will not find the `service` method in it. I'm not sure what is the best approach to circumvent this. But you could use this https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-9.html#-ts-expect-error-comments – Micael Levi May 29 '21 at 20:03
  • Not sure about that one either – hikvineh May 30 '21 at 14:18

2 Answers2

4

Its unclear if you are using the NestJS cache-manager wrapper, if so you need to use the provider token when injecting and the type would be Cache.

export function ClearCache() {
    
    const injector = Inject(CACHE_MANAGER)

    return (target: any, _key?: string | symbol, descriptor?: TypedPropertyDescriptor<any>) => {
        
        injector(target, 'cacheManager')

        const originalMethod = descriptor.value

        descriptor.value = async function (...args: any[]) {
            try {
                const service: Cache = this.cacheManager
                service.delete(args[1])
                return await originalMethod.apply(this, args)
            } catch (err) {
                console.error(err)
                return originalMethod(args)
            }
        }
    }
}

If it is a different service, ensure that you are using the correct provider token, it is in the current modules scope and instantiated. If it isn't in current module, check it is global

Uploaded minimal repo of above code here.

Update:

tsconfig.json has "strict":true. If it is enabled, then "this" would be strictly use the PropertyDescriptor interface.

Fixed the issue by changing "strict": false in the tsconfig.json.

hikvineh
  • 150
  • 1
  • 10
The Geek
  • 1,185
  • 9
  • 12
  • I've got the cache manager injected in CacheService, it's inside the same module, but not injected in the controller. – hikvineh May 30 '21 at 13:35
  • 1
    is the value of your injectCacheService defined and your CacheService have the @Injectable decorator? It could help to see a minimal repo to reproduce. – The Geek May 30 '21 at 13:47
  • The injectCacheService already has the Injectable decorator. but the injectCacheService only has [Function (anonymous)]... – hikvineh May 30 '21 at 14:12
  • Your code snippet above still has `Property 'cacheManager' does not exist on type 'TypedPropertyDescriptor'` – hikvineh May 30 '21 at 14:26
  • That’s copy pasted from a fresh app I spun up just for your question and it worked fine. I’ll post it tomorrow’s am away from compy but the issue will be is that the service is not in scope. As above, it would help if you could post a minimal repo – The Geek May 30 '21 at 19:30
  • ah I missed the minimal repo part , I'll get that one ready... Anyways, thank you so much! – hikvineh May 30 '21 at 19:44
  • No worries, I know how frustrating these things can be so just powered up my box and pushed the repo up. Link in my answer. – The Geek May 30 '21 at 20:10
  • I can't seem to find the repo @The Geek – hikvineh May 31 '21 at 03:54
  • Am an idiot. Was a private repo... made it public now :) – The Geek May 31 '21 at 07:15
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/233123/discussion-between-hikvineh-and-the-geek). – hikvineh May 31 '21 at 09:49
0

You can fix it easier with the follow: const service: CacheService = (this as any).service;

Greetings, Florian

Flo
  • 2,232
  • 2
  • 11
  • 18