diff --git a/packages/node-cache/src/index.ts b/packages/node-cache/src/index.ts index 6516e239..770016c4 100644 --- a/packages/node-cache/src/index.ts +++ b/packages/node-cache/src/index.ts @@ -264,14 +264,16 @@ export class NodeCache extends Hookified { * @param {Array} an object with the key as a property and the value as the value */ - public mget(keys: Array): Record { - const result: Record = {}; + public mget( + keys: Array, + ): Record { + const result: Record = {}; for (const key of keys) { const value = this.get(key); /* v8 ignore next -- @preserve */ if (value) { - result[this.formatKey(key)] = value as T; + result[this.formatKey(key)] = value as V; } } @@ -284,16 +286,16 @@ export class NodeCache extends Hookified { * @param {string | number} key * @returns {T | undefined} the value or undefined */ - public take(key: string | number): T | undefined { + public take(key: string | number): V | undefined { const result = this.get(key); if (result) { this.del(key); if (this.options.useClones) { - return this.clone(result) as T; + return this.clone(result) as V; } - return result as T; + return result as V; } return undefined; diff --git a/packages/node-cache/src/store.ts b/packages/node-cache/src/store.ts index e3cc8ca3..05aa1754 100644 --- a/packages/node-cache/src/store.ts +++ b/packages/node-cache/src/store.ts @@ -136,8 +136,8 @@ export class NodeCacheStore extends Hookified { * @param {string | number} key * @returns {any | undefined} */ - public async get(key: string | number): Promise { - const result = await this._keyv.get(key.toString()); + public async get(key: string | number): Promise { + const result = await this._keyv.get(key.toString()); if (result !== undefined) { this._stats.incrementHits(); } else { @@ -152,12 +152,12 @@ export class NodeCacheStore extends Hookified { * @param {Array} keys * @returns {Record} */ - public async mget( + public async mget( keys: Array, - ): Promise> { - const result: Record = {}; + ): Promise> { + const result: Record = {}; for (const key of keys) { - const value = await this._keyv.get(key.toString()); + const value = await this._keyv.get(key.toString()); if (value !== undefined) { this._stats.incrementHits(); } else { @@ -233,8 +233,8 @@ export class NodeCacheStore extends Hookified { * @param {string | number} key * @returns {T | undefined} */ - public async take(key: string | number): Promise { - const result = await this._keyv.get(key.toString()); + public async take(key: string | number): Promise { + const result = await this._keyv.get(key.toString()); if (result !== undefined) { this._stats.incrementHits(); await this._keyv.delete(key.toString()); diff --git a/packages/node-cache/test/index.test.ts b/packages/node-cache/test/index.test.ts index 8cfd976f..f86d89c4 100644 --- a/packages/node-cache/test/index.test.ts +++ b/packages/node-cache/test/index.test.ts @@ -392,4 +392,27 @@ describe("NodeCache", () => { cache.set("nullKey", null); expect(cache.get("nullKey")).toBe(null); }); + + test("should propagate class-level generic type through mget and take", () => { + type MyType = { name: string; age: number }; + const cache = new NodeCache({ checkperiod: 0 }); + cache.set("user1", { name: "Alice", age: 30 }); + cache.set("user2", { name: "Bob", age: 25 }); + + const mgetResult = cache.mget(["user1", "user2"]); + // Verify the type is correctly inferred as Record + const user1 = mgetResult.user1; + expect(user1).toBeDefined(); + expect(user1!.name).toBe("Alice"); + expect(user1!.age).toBe(30); + + const taken = cache.take("user2"); + // Verify the type is correctly inferred as MyType | undefined + expect(taken).toBeDefined(); + expect(taken!.name).toBe("Bob"); + expect(taken!.age).toBe(25); + + // Verify take removed the key + expect(cache.get("user2")).toBeUndefined(); + }); }); diff --git a/packages/node-cache/test/store.test.ts b/packages/node-cache/test/store.test.ts index dfa9aa0a..41fa1a8e 100644 --- a/packages/node-cache/test/store.test.ts +++ b/packages/node-cache/test/store.test.ts @@ -163,4 +163,31 @@ describe("NodeCacheStore", () => { const result = await store.get("test"); expect(result).toBe("value"); }); + + test("should propagate class-level generic type through get, mget, and take", async () => { + type MyType = { name: string; age: number }; + const store = new NodeCacheStore(); + await store.set("user1", { name: "Alice", age: 30 }); + await store.set("user2", { name: "Bob", age: 25 }); + + const getResult = await store.get("user1"); + expect(getResult).toBeDefined(); + expect(getResult?.name).toBe("Alice"); + expect(getResult?.age).toBe(30); + + const mgetResult = await store.mget(["user1", "user2"]); + const user1 = mgetResult.user1; + expect(user1).toBeDefined(); + expect(user1?.name).toBe("Alice"); + expect(user1?.age).toBe(30); + + const taken = await store.take("user2"); + expect(taken).toBeDefined(); + expect(taken?.name).toBe("Bob"); + expect(taken?.age).toBe(25); + + // Verify take removed the key + const afterTake = await store.get("user2"); + expect(afterTake).toBeUndefined(); + }); });