Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Named return type for createCache() method in cache-manager #923

Closed
PoOwAa opened this issue Dec 6, 2024 · 0 comments
Closed

Add Named return type for createCache() method in cache-manager #923

PoOwAa opened this issue Dec 6, 2024 · 0 comments

Comments

@PoOwAa
Copy link
Contributor

PoOwAa commented Dec 6, 2024

Issue Title

Add Named Return Type for createCache() Method in cache-manager

Description

The createCache() method in the cache-manager package currently lacks a named return type. This results in challenges for developers working with TypeScript, particularly in dependency injection frameworks like NestJS. Without a named return type, users must define their own types or rely on any, which undermines type safety and maintainability.

Problem Statement

In cache-manager v6, the createCache() method returns an object with various methods such as get, set, del, etc. However, this return type is inferred and not explicitly defined as a named type. This creates the following issues:

  • The return type of the cache instance must be manually defined in the provider or service.
  • Users cannot leverage TypeScript's type inference and autocomplete effectively.
  • Updates to the cache-manager package could inadvertently break user implementations due to lack of strong type definitions.

Example of the current usage in a NestJS service:

// cache-manager.module.ts
import { Module } from '@nestjs/common';
import { cacheManagerProvider } from './cache-manager.provider';

@Module({
  controllers: [],
  providers: [cacheManagerProvider],
  exports: [cacheManagerProvider],
})
export class CacheManagerModule {}
// cache-manager.provider.ts
import KeyvRedis from '@keyv/redis';
import { Provider } from '@nestjs/common';
import { createCache } from 'cache-manager';
import { CacheableMemory } from 'cacheable';
import Keyv from 'keyv';

export const cacheManagerProvider: Provider = {
  provide: 'CACHE_MANAGER',
  useFactory: () => {
    const stores: Keyv[] = [];

    stores.push(
      new Keyv({
        store: new CacheableMemory({ ttl: 60 * 60 * 1000, lruSize: 5000 }),
      })
    );

    if (process.env.REDIS_URL) {
      stores.push(
        new Keyv({
          store: new KeyvRedis(process.env.REDIS_URL),
        })
      );
    }

    const cache = createCache({
      stores,
    });

    return cache;
  },
};
export class ExampleService {
  constructor(
    @Inject('CACHE_MANAGER') private readonly cache: any, // there is no named type in the package
  ) {}

  async getCachedData(key: string): Promise<any> {
    return this.cache.get(key); // IDE has no idea about the syntax here, since this.cache is any
  }
}

The cache property is typed as any, which undermines the benefits of using TypeScript.

Suggested Solution

Introduce a new named interface, CacheInstance, that explicitly defines the shape of the object returned by createCache(). The method would then return this named type, improving type safety and usability.

Proposed Interface

export interface CacheInstance {
  get<T>(key: string): Promise<T | null>;
  mget<T>(keys: string[]): Promise<[T]>;
  set<T>(key: string, value: T, ttl?: number): Promise<T>;
  mset<T>(list: Array<{ key: string; value: T; ttl?: number }>): Promise<Array<{ key: string; value: T; ttl?: number }>>;
  del(key: string): Promise<boolean>;
  mdel(keys: string[]): Promise<boolean>;
  clear(): Promise<boolean>;
  wrap<T>(
    key: string,
    fnc: () => T | Promise<T>,
    ttl?: number | ((value: T) => number),
    refreshThreshold?: number
  ): Promise<T>;
  on<E extends keyof Events>(event: E, listener: Events[E]): EventEmitter<[never]>;
  off<E extends keyof Events>(event: E, listener: Events[E]): EventEmitter<[never]>;
  disconnect(): Promise<undefined>;
}

Updated Method Signature

export function createCache(): CacheInstance {
  // Implementation remains the same
}

Benefits

  • Type Safety: Developers can now reference CacheInstance directly in their code, ensuring compatibility with the latest cache-manager changes.
  • Improved DX: Enhanced type inference and autocomplete when using cache instances.
  • Easier Integration: Users of frameworks like NestJS can seamlessly inject and use the cache-manager instance without defining custom types.

Example Usage in NestJS

// example.service.ts
import { CacheInstance } from 'cache-manager';

export class ExampleService {
  constructor(
    @Inject('CACHE_MANAGER') private readonly cache: CacheInstance,
  ) {}

  async getCachedData(key: string): Promise<any> {
    return this.cache.get(key);
  }
}

Additional Notes

This change would greatly enhance the developer experience and ensure stronger type guarantees for users of the cache-manager package, particularly in TypeScript projects. A named return type would also help maintain compatibility during future updates to the package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants