Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions packages/node-cache/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,14 +264,16 @@ export class NodeCache<T> extends Hookified {
* @param {Array<string | number} keys an array of keys
* @returns {Record<string, T | undefined>} an object with the key as a property and the value as the value
*/
public mget<T>(keys: Array<string | number>): Record<string, T | undefined> {
const result: Record<string, T | undefined> = {};
public mget<V = T>(
keys: Array<string | number>,
): Record<string, V | undefined> {
const result: Record<string, V | undefined> = {};

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;
}
}

Expand All @@ -284,16 +286,16 @@ export class NodeCache<T> extends Hookified {
* @param {string | number} key
* @returns {T | undefined} the value or undefined
*/
public take<T>(key: string | number): T | undefined {
public take<V = T>(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;
Expand Down
16 changes: 8 additions & 8 deletions packages/node-cache/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ export class NodeCacheStore<T> extends Hookified {
* @param {string | number} key
* @returns {any | undefined}
*/
public async get<T>(key: string | number): Promise<T | undefined> {
const result = await this._keyv.get<T>(key.toString());
public async get<V = T>(key: string | number): Promise<V | undefined> {
const result = await this._keyv.get<V>(key.toString());
if (result !== undefined) {
this._stats.incrementHits();
} else {
Expand All @@ -152,12 +152,12 @@ export class NodeCacheStore<T> extends Hookified {
* @param {Array<string | number>} keys
* @returns {Record<string, any | undefined>}
*/
public async mget<T>(
public async mget<V = T>(
keys: Array<string | number>,
): Promise<Record<string, T | undefined>> {
const result: Record<string, T | undefined> = {};
): Promise<Record<string, V | undefined>> {
const result: Record<string, V | undefined> = {};
for (const key of keys) {
const value = await this._keyv.get<T>(key.toString());
const value = await this._keyv.get<V>(key.toString());
if (value !== undefined) {
this._stats.incrementHits();
} else {
Expand Down Expand Up @@ -233,8 +233,8 @@ export class NodeCacheStore<T> extends Hookified {
* @param {string | number} key
* @returns {T | undefined}
*/
public async take<T>(key: string | number): Promise<T | undefined> {
const result = await this._keyv.get<T>(key.toString());
public async take<V = T>(key: string | number): Promise<V | undefined> {
const result = await this._keyv.get<V>(key.toString());
if (result !== undefined) {
this._stats.incrementHits();
await this._keyv.delete(key.toString());
Expand Down
23 changes: 23 additions & 0 deletions packages/node-cache/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<MyType>({ 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<string, MyType | undefined>
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();
});
});
27 changes: 27 additions & 0 deletions packages/node-cache/test/store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<MyType>();
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();
});
});
Loading