or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-memoize-one

A memoization library which only remembers the latest invocation

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/memoize-one@6.0.x

To install, run

npx @tessl/cli install tessl/npm-memoize-one@6.0.0

index.mddocs/

Memoize One

Memoize One is a lightweight memoization library that implements a unique single-cache strategy, storing only the most recent function call result and arguments. Unlike traditional memoization libraries that maintain multiple cached entries with complex cache management, memoize-one simplifies memory usage by remembering only the latest invocation, automatically discarding previous results when new arguments are provided.

Package Information

  • Package Name: memoize-one
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install memoize-one

Core Imports

import memoizeOne from "memoize-one";
import type { EqualityFn, MemoizedFn } from "memoize-one";

For CommonJS:

const memoizeOne = require("memoize-one");

Basic Usage

import memoizeOne from "memoize-one";

// Simple function memoization
function add(a: number, b: number): number {
  return a + b;
}

const memoizedAdd = memoizeOne(add);

memoizedAdd(1, 2); // Function called, returns 3
memoizedAdd(1, 2); // Cache hit, returns 3 (function not called)
memoizedAdd(2, 3); // New arguments, function called, returns 5
memoizedAdd(1, 2); // Cache miss (not the latest), function called again

// Clear cache manually
memoizedAdd.clear();

Architecture

Memoize One uses a simple, memory-efficient architecture:

  • Single Cache Strategy: Only stores the most recent function call result, arguments, and context
  • Automatic Cache Invalidation: Previous results are automatically discarded when new arguments are provided
  • Context Sensitivity: Handles this context changes by invalidating the cache
  • Custom Equality: Supports custom argument comparison functions for complex data types
  • Type Safety: Full TypeScript support with generic function signature preservation

Capabilities

Memoization Function

Creates a memoized version of any function that remembers only the latest invocation result.

/**
 * Creates a memoized version of the provided function
 * @param resultFn - The function to be memoized
 * @param isEqual - Optional custom equality function for comparing arguments
 * @returns Memoized function with clear() method
 */
function memoizeOne<TFunc extends (this: any, ...newArgs: any[]) => any>(
  resultFn: TFunc,
  isEqual?: EqualityFn<TFunc>
): MemoizedFn<TFunc>;

Usage Examples:

import memoizeOne from "memoize-one";

// Basic memoization
const expensiveCalculation = (x: number, y: number) => {
  console.log("Computing...");
  return Math.pow(x, y);
};

const memoized = memoizeOne(expensiveCalculation);
memoized(2, 8); // Logs "Computing...", returns 256
memoized(2, 8); // No log, returns 256 from cache

// With custom equality function
import isDeepEqual from "lodash.isequal";

const processObjects = (data: any[]) => data.map(item => ({ ...item, processed: true }));
const memoizedProcess = memoizeOne(processObjects, isDeepEqual);

memoizedProcess([{ id: 1 }]); // Function called
memoizedProcess([{ id: 1 }]); // Cache hit with deep equality

Custom Equality Function

Defines how arguments are compared to determine cache hits.

/**
 * Function type for custom argument equality comparison
 * @param newArgs - New function arguments
 * @param lastArgs - Previously cached arguments
 * @returns True if arguments are considered equal (cache hit)
 */
type EqualityFn<TFunc extends (...args: any[]) => any> = (
  newArgs: Parameters<TFunc>,
  lastArgs: Parameters<TFunc>
) => boolean;

Usage Examples:

import memoizeOne, { EqualityFn } from "memoize-one";

// Shallow equality for array contents
const shallowArrayEqual: EqualityFn<(arr: number[]) => number> = (newArgs, lastArgs) => {
  const [newArr] = newArgs;
  const [lastArr] = lastArgs;
  return newArr.length === lastArr.length && 
         newArr.every((val, idx) => val === lastArr[idx]);
};

const sumArray = (arr: number[]) => arr.reduce((sum, val) => sum + val, 0);
const memoizedSum = memoizeOne(sumArray, shallowArrayEqual);

memoizedSum([1, 2, 3]); // Function called
memoizedSum([1, 2, 3]); // Cache hit (shallow equal)

Memoized Function Interface

The enhanced function returned by memoizeOne with additional cache management.

/**
 * Enhanced function interface with cache management
 */
type MemoizedFn<TFunc extends (this: any, ...args: any[]) => any> = {
  /** Clears the cached result and arguments */
  clear(): void;
  /** The original function signature with preserved context and types */
  (this: ThisParameterType<TFunc>, ...args: Parameters<TFunc>): ReturnType<TFunc>;
};

Usage Examples:

import memoizeOne from "memoize-one";

const fibonacci = (n: number): number => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
};

const memoizedFib = memoizeOne(fibonacci);

memoizedFib(10); // Computed
memoizedFib(10); // From cache

// Clear cache when needed
memoizedFib.clear();
memoizedFib(10); // Computed again

// Works with context (this)
class Calculator {
  multiplier = 2;
  
  multiply = memoizeOne((value: number) => {
    return value * this.multiplier;
  });
}

const calc = new Calculator();
calc.multiply(5); // Returns 10
calc.multiply(5); // From cache

Default Equality Behavior

By default, memoize-one uses shallow equality comparison with special NaN handling:

  1. Argument Count: Arguments must have the same length
  2. Strict Equality: Each argument uses === comparison
  3. NaN Special Case: Two NaN values are considered equal (unlike normal ===)
  4. Context Sensitivity: Changes to this context automatically invalidate cache

Examples:

const memoized = memoizeOne((a, b) => a + b);

// Same arguments - cache hit
memoized(1, 2); // Computed
memoized(1, 2); // Cache hit

// Different argument count - cache miss
memoized(1, 2, 3); // Computed (different arg count)

// NaN handling
const memoizedNaN = memoizeOne((x) => x);
memoizedNaN(NaN); // Computed
memoizedNaN(NaN); // Cache hit (NaN === NaN in memoize-one)

// Object references
memoized({ id: 1 }, { id: 2 }); // Computed
memoized({ id: 1 }, { id: 2 }); // Cache miss (different object references)

Error Handling

When the memoized function throws an error, memoize-one handles it with specific behavior:

  1. Exception Propagation: If the memoized function throws, the memoized function also throws
  2. No Caching of Errors: Thrown results are never cached - each call with arguments that cause an exception will re-execute the function
  3. Cache Preservation: Previous successful cache results remain intact even when exceptions occur

Examples:

import memoizeOne from "memoize-one";

const canThrow = (shouldThrow: boolean, value: number) => {
  if (shouldThrow) {
    throw new Error("Something went wrong");
  }
  return value * 2;
};

const memoized = memoizeOne(canThrow);

// Successful call - result cached
const result1 = memoized(false, 5); // Returns 10, cached

// Exception call - no caching
try {
  memoized(true, 3); // Throws Error, not cached
} catch (e) {
  console.log("First error:", e.message);
}

// Same exception call - function called again (no cache)
try {
  memoized(true, 3); // Throws Error again, function re-executed
} catch (e) {
  console.log("Second error:", e.message);
}

// Previous successful result still cached
const result2 = memoized(false, 5); // Returns 10 from cache (not re-executed)
console.log(result1 === result2); // true