SkillAgentSearch skills...

Moize

The consistently-fast, complete memoization solution for JS

Install / Use

/learn @planttheidea/Moize
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

[!CAUTION] This library has been deprecated in favor of micro-memoize, which as-of version 5 incorporates most of the functionality that this library offers at nearly half the size and better speed. It is recommended to migrate to micro-memoize@latest, and you can use the migration guide to help with any specific changes to your codebase.

moize

<img src="https://img.shields.io/badge/build-passing-brightgreen.svg"/> <img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"/> <img src="https://img.shields.io/badge/license-MIT-blue.svg"/>

moize is a consistently blazing fast memoization library for JavaScript. It handles multiple parameters (including default values) without any additional configuration, and offers a large number of options to satisfy any number of potential use-cases.

$ npm i moize --save

Importing

ESM in browsers

import moize from 'moize';

ESM in NodeJS

import moize from 'moize/mjs/index.mjs';

CommonJS

const moize = require('moize');

Usage

import moize from 'moize';

const method = (a: number, b: number) => a + b;

const memoized = moize(method);

memoized(2, 4); // 6
memoized(2, 4); // 6, pulled from cache

All parameter types are supported, including circular objects, functions, etc. There are also a number of shortcut methods to memoize for unique use-cases.

Configuration options

moize optionally accepts an object of options as either the second parameter or as the first step in a curried function:

// inline
moize(fn, options);

// curried
moize(options)(fn);

The full shape of these options:

type Options = {
    // is the cache based on deep equality of each key argument
    isDeepEqual: boolean;
    // is the result a promise
    isPromise: boolean;
    // is the result a React component
    isReact: boolean;
    // should the parameters be serialized instead of directly referenced
    isSerialized: boolean;
    // is the cache based on shallow equality of each key argument
    isShallowEqual: boolean;
    // custom method to compare equality between two key arguments
    matchesArg: (cachedKeyArg: any, keyArg: any) => boolean;
    // custom method to compare equality across all key arguments
    matchesKey: (cachedKey: any[], key: any[]) => boolean;
    // amount of time in milliseconds before the cache will expire
    maxAge: number;
    // maximum number of arguments passed to use as key for caching
    maxArgs: number;
    // maximum size of cache for this method
    maxSize: number;
    // method fired when a new entry is added to cache
    onCacheAdd: (
        cache: moize.Cache,
        options: moize.Options,
        moized: (...args: any[]) => any
    ) => void;
    // method fire when either a new entry is added to cache or the LRU ordering of the cache has changed
    onCacheChange: (
        cache: moize.Cache,
        options: moize.Options,
        moized: (...args: any[]) => any
    ) => void;
    // method fired when an existing entry in cache is used
    onCacheHit: (
        cache: moize.Cache,
        options: moize.Options,
        moized: (...args: any[]) => any
    ) => void;
    // method to fire when a cache entry expires (in combination with maxAge)
    onExpire: (key: any[]) => void;
    // the unique identifier to give the memoized method when collecting statistics
    profileName: string;
    // method to serialize the arguments to build a unique cache key
    serializer: (key: any[]) => string;
    // method to transform the args into a custom format for key storage in cache
    transformArgs: (key: any[]) => any[];
    // should the cache entry be refreshed by calling the underlying function with the same parameters and
    // updating the value stored in cache to be the new result
    updateCacheForKey: (key: any[]) => boolean;
    // should the cache entry's expiration be refreshed when the cache entry is hit (in combination with maxAge)
    updateExpire: boolean;
};

All default values can be found here.

isDeepEqual

defaults to false

Should deep equality be used to compare cache each key argument.

type Arg = {
    one: {
        nested: string;
    };
    two: string;
};

const fn = ({ one, two }: Arg) => [one, two];

const memoized = moize(fn, { isDeepEqual: true });

memoized({ one: { nested: 'one' }, two: 'two' });
memoized({ one: { nested: 'one' }, two: 'two' }); // pulls from cache

This is also available via the shortcut method of moize.deep

const memoized = moize.deep(fn);

isPromise

defaults to false

Is the computed value in the function a Promise.

const fn = async (item: Promise<string>) => await item;

const memoized = moize(fn, { isPromise: true });

This is also available via the shortcut method of moize.promise.

const memoized = -moize.promise(fn);

The Promise itself will be stored in cache, so that cached returns will always maintain the Promise contract. For common usage reasons, if the Promise is rejected, the cache entry will be deleted.

isReact

defaults to false

Is the function passed a stateless functional React component.

type Props = {
    one: string;
    two: number;
};

const Component = ({ one, two }: Props) => (
    <div>
        {one}: {two}
    </div>
);

const MemoizedFoo = moize(Component, { isReact: true });

This is also available via the shortcut method of moize.react.

const MemoizedFoo = moize.react(Component);

The method will do a shallow equal comparison of both props and legacy context of the component based on strict equality. If you want to do a deep equals comparison, set isDeepEqual to true.

NOTE: This will memoize on each instance of the component passed, which is equivalent to PureComponent or React.memo. If you want to memoize on all instances (which is how this option worked prior to version 6), use the following options:

const memoized = moize(Component, { isShallowEqual: true, maxArgs: 2 });

isSerialized

defaults to false

Serializes the parameters passed into a string and uses this as the key for cache comparison.

const fn = (mutableObject: { one: Record<string, any> }) =>
    mutableObject.property;

const memoized = moize(fn, { isSerialized: true });

This is also available via the shortcut method of moize.serialize.

const memoized = moize.serialize(fn);

If serialize is combined with either maxArgs or transformArgs, the following order is used:

  1. limit by maxArgs (if applicable)
  2. transform by transformArgs (if applicable)
  3. serialize by serializer

NOTE: This is much slower than the default key storage, and usually the same requirements can be meet with isDeepEqual, so use at your discretion.

isShallowEqual

defaults to false

Should shallow equality be used to compare cache each key argument.

type Arg = {
    one: string;
    two: string;
};

const fn = ({ one, two }: Arg) => [one, two];

const memoized = moize(fn, { isShallowEqual: true });

memoized({ one: 'one', two: 'two' });
memoized({ one: 'one', two: 'two' }); // pulls from cache

This is also available via the shortcut method of moize.shallow

const memoized = moize.shallow(fn);

matchesArg

_defaults to SameValueZero equ

Related Skills

View on GitHub
GitHub Stars917
CategoryDevelopment
Updated3h ago
Forks19

Languages

TypeScript

Security Score

100/100

Audited on Apr 4, 2026

No findings