{"id":12759,"library":"typescript-memoize","title":"TypeScript Method Memoization Decorator","description":"typescript-memoize is a decorator library for TypeScript that enables method and getter memoization, primarily for optimizing performance by caching the results of expensive operations. As of version 1.1.1, it provides `@Memoize` for standard caching and `@MemoizeExpiring` for time-limited caching, which automatically invalidates cached values after a specified duration. The library offers flexibility in how memoization keys are generated, supporting methods without parameters, `get` accessors, and methods where memoization is based on specific parameters or custom hash functions. It's a stable library, though release cadence is not explicitly defined, new versions appear infrequently. Its key differentiator lies in its decorator-based approach, integrating seamlessly with TypeScript classes, and allowing for granular control over cache invalidation via custom hash functions or expiration.","status":"active","version":"1.1.1","language":"javascript","source_language":"en","source_url":"https://github.com/darrylhodgins/typescript-memoize","tags":["javascript","typescript","memoize","functional","decorator"],"install":[{"cmd":"npm install typescript-memoize","lang":"bash","label":"npm"},{"cmd":"yarn add typescript-memoize","lang":"bash","label":"yarn"},{"cmd":"pnpm add typescript-memoize","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary decorator for caching method or getter results. Requires 'experimentalDecorators' and 'emitDecoratorMetadata' in tsconfig.json.","wrong":"const Memoize = require('typescript-memoize');","symbol":"Memoize","correct":"import { Memoize } from 'typescript-memoize';"},{"note":"Used for caching with automatic invalidation after a specified time in milliseconds.","wrong":"import MemoizeExpiring from 'typescript-memoize';","symbol":"MemoizeExpiring","correct":"import { MemoizeExpiring } from 'typescript-memoize';"},{"note":"Pass a function to `@Memoize` to define how cache keys are generated from method arguments, useful for complex parameter types or multi-parameter methods.","symbol":"Custom Hash Function","correct":"@Memoize((param1: any, param2: any) => `${param1}-${param2}`)"}],"quickstart":{"code":"import { Memoize, MemoizeExpiring } from 'typescript-memoize';\n\nclass DataService {\n    private callCount: number = 0;\n\n    @Memoize()\n    public getExpensiveData(): string {\n        this.callCount++;\n        console.log(`Fetching expensive data... (call count: ${this.callCount})`);\n        return `Data fetched at ${new Date().toISOString()}`;\n    }\n\n    @MemoizeExpiring(3000) // Cache expires after 3 seconds\n    public getExpiringData(param: string): string {\n        console.log(`Fetching expiring data for '${param}'...`);\n        return `Expiring data for ${param} at ${new Date().toISOString()}`;\n    }\n\n    // Custom hash function for memoizing based on multiple parameters\n    @Memoize((id: number, type: string) => `${id}-${type}`)\n    public getItem(id: number, type: string): string {\n        console.log(`Fetching item ${id} of type ${type}...`);\n        return `Item ${id} (${type}) retrieved at ${new Date().toISOString()}`;\n    }\n}\n\nasync function runExample() {\n    const service = new DataService();\n\n    console.log(\"--- Standard Memoize ---\");\n    console.log(service.getExpensiveData()); // Fetches\n    console.log(service.getExpensiveData()); // Returns cached\n    console.log(service.getExpensiveData()); // Returns cached\n\n    console.log(\"\\n--- Expiring Memoize ---\");\n    console.log(service.getExpiringData(\"A\")); // Fetches\n    console.log(service.getExpiringData(\"A\")); // Returns cached\n    await new Promise(resolve => setTimeout(resolve, 3100)); // Wait for cache to expire\n    console.log(service.getExpiringData(\"A\")); // Fetches again after expiration\n\n    console.log(\"\\n--- Custom Hash Function Memoize ---\");\n    console.log(service.getItem(1, \"book\")); // Fetches\n    console.log(service.getItem(1, \"book\")); // Returns cached\n    console.log(service.getItem(2, \"book\")); // Different key, fetches\n    console.log(service.getItem(1, \"movie\")); // Different key, fetches\n}\n\nrunExample();","lang":"typescript","description":"Demonstrates basic `@Memoize`, `@MemoizeExpiring` with a time limit, and `@Memoize` with a custom hash function for complex parameters, showing cache hits and expirations in a class context."},"warnings":[{"fix":"Ensure `tsconfig.json` includes `\"experimentalDecorators\": true, \"emitDecoratorMetadata\": true` under `compilerOptions`.","message":"TypeScript decorators require specific compiler options (`\"experimentalDecorators\": true` and usually `\"emitDecoratorMetadata\": true`) in `tsconfig.json` to function correctly.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Provide a custom hash function to `@Memoize(hashFunction)` that generates a unique key based on all relevant parameters. For example: `@Memoize((p1, p2) => `${p1}-${p2}`).","message":"When `@Memoize()` is applied to a method with multiple parameters *without* a custom hash function, it will by default only use the *first* parameter for memoization key generation. Subsequent parameters are ignored for caching purposes, potentially leading to incorrect cached values if the method's result depends on later parameters.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Consider using `MemoizeExpiring` if you need time-based invalidation, or implement a custom memoization solution or a wrapper around `typescript-memoize` that exposes cache clearing functionality if dynamic invalidation is crucial.","message":"The library does not provide a public API for manual cache invalidation beyond the `MemoizeExpiring` decorator. If you need to clear the cache for a non-expiring memoized method dynamically, you would need to recreate the class instance or implement custom cache invalidation logic.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Add or ensure `\"experimentalDecorators\": true` and `\"emitDecoratorMetadata\": true` in the `compilerOptions` section of your `tsconfig.json`.","cause":"TypeScript compiler options for decorators are not correctly configured, often missing `emitDecoratorMetadata`.","error":"TypeError: Cannot read properties of undefined (reading '__metadata')"},{"fix":"Use ES Module import syntax: `import { Memoize } from 'typescript-memoize';`","cause":"Attempting to import or use the decorator with CommonJS `require()` syntax or incorrect destructuring in an ES Module context.","error":"TypeError: (0 , typescript_memoize_1.Memoize) is not a function"}],"ecosystem":"npm"}