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

Allow TS typing of cached value: new NodeCache<MyType>(...) #273

Open
ThomasAribart opened this issue Dec 6, 2021 · 7 comments · May be fixed by #315
Open

Allow TS typing of cached value: new NodeCache<MyType>(...) #273

ThomasAribart opened this issue Dec 6, 2021 · 7 comments · May be fixed by #315

Comments

@ThomasAribart
Copy link

This would allow custom type enforcing to all methods.

const cachedValue = cache.get(...) // => undefined | MyType
cache.set(...) // => Invalid if value is not assignable to MyType
@ThomasAribart ThomasAribart changed the title Allow typing of cached value: new NodeCache<MyType>(...) Allow TS typing of cached value: new NodeCache<MyType>(...) Dec 6, 2021
@ThomasAribart
Copy link
Author

Up

@Setitch
Copy link

Setitch commented May 18, 2022

+1

@ThijmenDam
Copy link

ThijmenDam commented Apr 12, 2023

We considered using node-cache module in our project, though the absence of this functionality is likely a deciding factor for not using it. So, definitely agree with the PR!

@mtsknn
Copy link

mtsknn commented Aug 22, 2023

This would be great. I was investigating a weird bug and was running out of ideas, until I noticed that one cache was accidentally being used for two different things.

I solved the issue by creating a type-safer wrapper around Node-Cache: Adding type-safety to Node-Cache.

@Mimickal
Copy link

I have been using this library in https://github.com/Mimickal/ReactionRoleBot. I am now porting the project to TypeScript and noticed I always need to specify the type on .get(), otherwise the result is unknown. This is not type safe without wrapping the library like @mtsknn did.

This issue has been open for nearly 2 years with no movement. Have the developers seen this issue?

@doc-han
Copy link

doc-han commented Sep 10, 2023

This project seems to be no more under maintenance,
find an alternative or build an internal one(will take some minutes to do so).

@ParallelUniv3rse
Copy link

I've taken the liberty to post a PR addressing this issue.
I've tried to keep it backwards compatible with the option to now define the value types beforehand on the cache class.

Until this is merged and released, I've managed to apply these changes to my project by overriding the module types in my own project type files (pretty much following the steps here: https://tomsoir.medium.com/typescript-how-to-rewrite-type-definition-file-file-d-ts-of-any-node-modules-package-1eed7f5630d1)

The code for my custom definition file is as follows:

import { Data, Options, Stats, Key, ValueSetItem } from 'node-cache'
import * as events from 'events'
/*
Custom typings for node-cache to allow defining value type on the class.
Related issue: https://github.com/node-cache/node-cache/issues/273
 */
declare module 'node-cache' {
    declare class NodeCache<ValueType = unknown> extends events.EventEmitter {
        /** container for cached data */
        data: Data

        /** module options */
        options: Options

        /** statistics container */
        stats: Stats

        /** constructor */
        constructor(options?: Options)

        /**
         * get a cached key and change the stats
         *
         * @param key cache key
         * @returns The value stored in the key
         */
        get<T extends ValueType>(key: Key): (ValueType extends unknown ? T : ValueType) | undefined

        /**
         * get multiple cached keys at once and change the stats
         *
         * @param keys an array of keys
         * @returns an object containing the values stored in the matching keys
         */
        mget<T extends ValueType>(
            keys: Key[],
        ): { [key: string]: ValueType extends unknown ? T : ValueType }

        /**
         * set a cached key and change the stats
         *
         * @param key cache key
         * @param value A element to cache. If the option `option.forceString` is `true` the module trys to translate
         * it to a serialized JSON
         * @param ttl The time to live in seconds.
         */
        set<T extends ValueType>(
            key: Key,
            value: ValueType extends unknown ? T : ValueType,
            ttl: number | string,
        ): boolean

        set<T extends ValueType>(
            key: Key,
            value: ValueType extends unknown ? T : ValueType,
        ): boolean

        /**
         * set multiple cached keys at once and change the stats
         *
         * @param keyValueSet an array of object which includes key,value and ttl
         */
        mset<T extends ValueType>(
            keyValueSet: ValueSetItem<ValueType extends unknown ? T : ValueType>[],
        ): boolean

        /**
         * remove keys
         * @param keys cache key to delete or a array of cache keys
         * @param cb Callback function
         * @returns Number of deleted keys
         */
        del(keys: Key | Key[]): number

        /**
         * get a cached key and remove it from the cache.
         * Equivalent to calling `get(key)` + `del(key)`.
         * Useful for implementing `single use` mechanism such as OTP, where once a value is read it will become obsolete.
         *
         * @param key cache key
         * @returns The value stored in the key
         */
        take<T extends ValueType>(key: Key): (ValueType extends unknown ? T : ValueType) | undefined

        /**
         * reset or redefine the ttl of a key. If `ttl` is not passed or set to 0 it's similar to `.del()`
         */
        ttl(key: Key, ttl: number): boolean

        ttl(key: Key): boolean

        getTtl(key: Key): number | undefined

        getTtl(key: Key): boolean

        /**
         * list all keys within this cache
         * @returns An array of all keys
         */
        keys(): string[]

        /**
         * get the stats
         *
         * @returns Stats data
         */
        getStats(): Stats

        /**
         * Check if a key is cached
         * @param key cache key to check
         * @returns Boolean indicating if the key is cached or not
         */
        has(key: Key): boolean

        /**
         * flush the whole data and reset the stats
         */
        flushAll(): void

        /**
         * This will clear the interval timeout which is set on checkperiod option.
         */
        close(): void

        /**
         * flush the stats and reset all counters to 0
         */
        flushStats(): void
    }

    export default NodeCache
}

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

Successfully merging a pull request may close this issue.

7 participants