TypeScript-based caching decorators

Q.s. Wang
2 min readApr 20, 2022

--

I am currently working on a smart building project which has dozens of services. Some of the services are providing the basic meta information, such as building, level, rooms and etc.

For the services that are using this data it’s a common practice for us to be providing the cache, as this data is relatively stable. With our typescript base API backend we’re able to implement our own currying [QW1] function to decorate the cache layer of the data accessing functions. [QW2] However, this solution was not as elegant as we had expected.

Recently we have found a NPM package at https://github.com/joshuaslate/type-cacheable which provides a typescript decorators based solution. I made the changes and I am quite happy with the result.

I am sharing the experiences of this type-cachable here.

At a high level we would like to

  1. Leverage the typescript decorators feature so that we can inject the cache layer by annotation on the function.

2. We’re using the redis as our cache solution in product but, we would like to use in memory cache for dev env so that we don’t have to run the redis locally.

Step 1 Enable the typescript decorators feature in the tsconfig.json file or your typescript configuration section

“experimentalDecorators”: true,

Step 2. Install the dependencis

npm install — save @type-cacheable/corenpm install — save @type-cacheable/core @type-cacheable/ioredis-adapternpm install — save @type-cacheable/core @type-cacheable/node-cache-adapter

Step 3. Init the cachable in your application globally.

const REDIS_DISABLED =
process.env.REDIS_DISABLED?.toLocaleLowerCase() === ‘true’;
CacheManager.setOptions({ ttlSeconds: 600 });if (REDIS_DISABLED) { const NodeAdapter = useNodeAdapter(new NodeCache()); CacheManager.setClient(NodeAdapter);} else { const redis = new IoRedis({ host: process.env.REDIS_HOST, port: process.env.REDIS_PORT ? parseInt(process.env.REDIS_PORT) : 6379,}); const IORedisAdapter = useIORedisAdapter(redis); CacheManager.setClient(IORedisAdapter);}

Step 4 decorate the cachable funtion

@Cacheable({ cacheKey: ‘v1.buildings’ })public getBuildings(): Promise<Building[]> {return this.client.get(‘/buildings’).then((res) => res.data);}

The type-cacheable is an elegant solution for us to setup the cache layer. The only concern is that the typescript decorators experimental is still a stage 2 proposal which may change in the future.

--

--