nestjsnode-rediscachemanager

How can I get redis io client from NestJS CacheManager module


I am currently using cache manager module from NestJS and I was wondering why I can't get the NodeRedis client like this :

 constructor(
    @Inject(CACHE_MANAGER) private cacheManager: Cache,
  ) {
    cacheManager.store.getClient();
  }

I am getting this error :

ERROR in [...].controller.ts:24:24
TS2339: Property 'getClient' does not exist on type 'Store'.
    22 |     @Inject(CACHE_MANAGER) private cacheManager: Cache,
    23 |   ) {
  > 24 |     cacheManager.store.getClient();
       |                        ^^^^^^^^^
    25 |   }

I did configured the cache-manager-redis-store when I registered the CacheModule then I supposed I could get the client.


Solution

  • tl;dr It seems that cache-manager-redis-store isn't properly supported by TypeScript because the RedisCache type is private and can't be imported.

    As a workaround, you could copy the private types to your own file:

    import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common';
    import { Store } from 'cache-manager';
    import Redis from 'redis';
    
    interface RedisCache extends Cache {
      store: RedisStore;
    }
    
    interface RedisStore extends Store {
      name: 'redis';
      getClient: () => Redis.RedisClient;
      isCacheableValue: (value: any) => boolean;
    }
    
    @Injectable()
    export class CacheService {
      constructor(
        @Inject(CACHE_MANAGER)
        private cacheManager: RedisCache,
      ) {
        cacheManager.store.getClient();
      }
    }

    Deep Dive

    It looks like the CACHE_MANAGER provided by NestJS is created by createCacheManager, which imports the npm package cache-manager and then invokes its caching function with the store package you give.

    I think the Cache type you're using is imported from cache-manager. The type is defined here and contains a Store contained here in the same file. getClient is not a method method on that interface, so the error message is correct.

    However, since you're using an external package for the store, there's more to it than caching-manager knows about. Looking at the types for cache-manager-redis-store, you can see there's a type RedisStore that extends Store and includes getClient.

    So cacheManager technically has getClient since you've configured it with the redis store package, but you need to set the type on your cacheManager variable to RedisCache for TypeScript to allow it.

    Based on the DefinitelyTyped types for cache-manager-redis-store, it seems your type should be redisStore.CacheManagerRedisStore.RedisCache if you imported the package as redisStore, but there seems to be an issue because that namespace CacheManagerRedisStore is not exported.

    There's an issue about this same problem on the repo and there's an issue asking for TypeScript support. It seems this package isn't properly supported by TypeScript at this time.