receta

Memo

15 exports from @ontologyio/receta/memo.

Everything exported from @ontologyio/receta/memo. New here? Start with the Memo guide.

Functions

clearCache

Clears the cache of a memoized function.

Signature
function clearCache<Args extends readonly unknown[], R>(memoized: MemoizedFunction<Args, R> | MemoizedAsyncFunction<Args, R>): void
Example
import { memoize, clearCache } from '@ontologyio/receta/memo'

const expensive = memoize((n: number) => fibonacci(n))

expensive(40) // computed
expensive(40) // cached

clearCache(expensive)

expensive(40) // computed again

// Alternative: use .clear() method
expensive.clear()

invalidateAll

Clears the cache of multiple memoized functions at once.

Useful for coordinated invalidation across related caches.

Signature
function invalidateAll(...memoized: AnyMemoized[]): void
Example
import { memoize, memoizeAsync, invalidateAll } from '@ontologyio/receta/memo'

const getUser = memoize(fetchUser)
const getUserPosts = memoizeAsync(fetchUserPosts)
const getUserComments = memoizeAsync(fetchUserComments)

// After user deletion
async function deleteUser(id: string) {
  await db.users.delete(id)

  // Clear all user-related caches
  invalidateAll(getUser, getUserPosts, getUserComments)
}

// Alternative: clear specific entries before clearing all
getUser.cache.delete(id)
getUserPosts.cache.delete(id)
invalidateAll(getUserComments) // Clear everything from this one

invalidateMany

Invalidates multiple cache entries by their keys.

Useful when you know specific keys to invalidate after a batch operation.

Signature
function invalidateMany<K>(memoized: AnyMemoized, keys: K[]): void
Example
import { memoize, invalidateMany } from '@ontologyio/receta/memo'

const getUser = memoize(fetchUser)

// After batch user update
await updateUsers(['1', '2', '3'], newData)
invalidateMany(getUser, ['1', '2', '3'])

// Next calls will recompute
getUser('1') // Fetched again
getUser('2') // Fetched again

invalidateWhere

Invalidates cache entries matching a predicate.

Useful for conditional invalidation based on key patterns or cached values.

Works with the default cache, ttlCache, lruCache and custom caches that have a forEach method. Throws for weakCache, because a WeakMap can't be listed.

Signature
function invalidateWhere<K = unknown, V = unknown>(memoized: AnyMemoized, predicate: (key: K, value?: V | undefined) => boolean): void
Example
import { memoizeBy, invalidateWhere } from '@ontologyio/receta/memo'

const getUser = memoizeBy(
  fetchUser,
  (id, type) => `${type}:${id}`
)

// Invalidate all admin users
invalidateWhere<string>(getUser, (key) => key.startsWith('admin:'))

// Invalidate by value condition
invalidateWhere<string, User>(getUser, (_key, user) => user?.deleted === true)

lruCache

Creates a Least-Recently-Used (LRU) cache with a maximum size.

When the cache reaches max size, the least recently accessed entry is evicted. Useful for limiting memory usage while keeping hot data cached.

Signature
function lruCache<K, V>(maxSize: number): Cache<K, V>
Example
import { memoize, lruCache } from '@ontologyio/receta/memo'

// Cache up to 100 users
const getUser = memoize(fetchUser, {
  cache: lruCache(100)
})

// After 100 different users:
getUser('user-001') // cached
getUser('user-002') // cached
// ... 100 more calls ...
getUser('user-101') // causes 'user-001' to be evicted

memoize

Creates a memoized version of a function that caches results based on arguments.

By default, uses a simple Map cache with the first argument as the key. For multi-argument functions or complex keys, use memoizeBy() instead.

Signature
function memoize<Args extends readonly [unknown, ...unknown[]], R>(fn: (...args: Args) => R, options?: MemoizeOptions<string>): MemoizedFunction<Args, R>
Example
// Basic memoization
const fibonacci = (n: number): number => {
  if (n <= 1) return n
  return fibonacci(n - 1) + fibonacci(n - 2)
}

const memoFib = memoize(fibonacci)
memoFib(40) // computed (takes time)
memoFib(40) // cached (instant)

// With max size
const getUser = memoize(fetchUser, { maxSize: 100 })

// With TTL
const getWeather = memoize(fetchWeather, { cache: ttlCache(5 * 60 * 1000) }) // 5 min

See also memoizeBy, memoizeAsync.

memoizeAsync

Creates a memoized async function with request deduplication.

Key features:

  • Caches resolved promises
  • Prevents duplicate in-flight requests (thundering herd protection)
  • Failed promises are not cached
  • Supports TTL and LRU cache strategies
Signature
function memoizeAsync<Args extends readonly unknown[], R>(fn: (...args: Args) => Promise<R>, options?: MemoizeOptions<string> & { keyFn?: KeyFn<Args, unknown> | undefined; }): MemoizedAsyncFunction<Args, R>
Example
// Basic async memoization
const fetchUser = memoizeAsync(async (id: string) => {
  const res = await fetch(`/api/users/${id}`)
  return res.json()
})

// Concurrent calls - only 1 fetch happens
const [a, b, c] = await Promise.all([
  fetchUser('123'),
  fetchUser('123'),
  fetchUser('123')
]) // All return same result from single API call

// With TTL
const getWeather = memoizeAsync(
  async (city: string) => api.fetchWeather(city),
  { cache: ttlCache(5 * 60 * 1000) } // 5 min cache
)

// Custom key extraction
const fetchData = memoizeAsync(
  async (opts: { id: string; type: string }) => api.fetch(opts),
  { keyFn: (opts) => `${opts.id}:${opts.type}` }
)

See also memoize, memoizeBy.

memoizeBy

Creates a memoized function with custom key extraction.

Use this when:

  • Function takes multiple arguments
  • Function takes complex objects as arguments
  • You need custom cache key logic
Signature
function memoizeBy<Args extends readonly unknown[], R, K>(fn: (...args: Args) => R, keyFn: KeyFn<Args, K>, options?: MemoizeOptions<K>): MemoizedFunction<Args, R>
Example
// Multi-argument function
const add = (a: number, b: number) => a + b
const memoAdd = memoizeBy(add, (a, b) => `${a},${b}`)

memoAdd(2, 3) // computed
memoAdd(2, 3) // cached

// Complex object arguments
interface FetchOptions {
  id: string
  include?: string[]
}

const fetchUser = memoizeBy(
  (opts: FetchOptions) => api.fetch(opts),
  (opts) => JSON.stringify(opts)
)

// Object key (use with WeakMap cache)
const processNode = memoizeBy(
  (node: Node) => expensiveOperation(node),
  (node) => node // object as key
)

See also memoize, memoizeAsync.

ttlCache

Creates a time-to-live (TTL) cache that automatically expires entries.

Entries are removed after the specified TTL duration. Useful for caching data that becomes stale (API responses, weather, prices, etc.).

Signature
function ttlCache<K, V>(ttlMs: number): Cache<K, V>
Example
import { memoize, ttlCache } from '@ontologyio/receta/memo'

// Cache weather data for 5 minutes
const getWeather = memoize(fetchWeather, {
  cache: ttlCache(5 * 60 * 1000)
})

getWeather('NYC') // fetches from API
getWeather('NYC') // cached
// ... 5 minutes later ...
getWeather('NYC') // fetches from API again

weakCache

Creates a WeakMap-based cache for object keys.

Advantages:

  • Entries are garbage collected when keys are no longer referenced
  • No memory leaks from unreferenced objects
  • Perfect for caching computations on DOM nodes, objects, etc.

Limitations:

  • Only works with object keys (not primitives)
  • Cannot iterate entries
  • No size limit or TTL support
Signature
function weakCache<K extends object, V>(): Cache<K, V>
Example
import { memoizeBy, weakCache } from '@ontologyio/receta/memo'

interface Node {
  id: string
  children: Node[]
}

const processNode = memoizeBy(
  (node: Node) => expensiveOperation(node),
  (node) => node, // object as key
  { cache: weakCache() }
)

const node = { id: 'root', children: [] }
processNode(node) // computed
processNode(node) // cached
// When 'node' is GC'd, cache entry is automatically removed

Types

Cache

Cache interface that memoization functions can use. Allows custom cache implementations (Map, LRU, TTL, WeakMap, etc.).

Signature
interface Cache<K, V> {
  get(key: K): Option<V>
  set(key: K, value: V): void
  has(key: K): boolean
  delete(key: K): boolean
  clear(): void
  forEach?(callback: (value: V, key: K) => void): void
}

KeyFn

Function that extracts a cache key from function arguments.

Signature
type KeyFn<Args extends readonly unknown[], K> = (...args: Args) => K

MemoizedAsyncFunction

A memoized async function with cache access and deduplication.

Signature
interface MemoizedAsyncFunction<Args extends readonly unknown[], R> {
  (...args: Args): Promise<R>
  cache: Cache<unknown, Promise<R>>
  clear: () => void
}

MemoizedFunction

A memoized function with cache access.

Signature
interface MemoizedFunction<Args extends readonly unknown[], R> {
  (...args: Args): R
  cache: Cache<unknown, R>
  clear: () => void
}

MemoizeOptions

Options for memoization functions.

Signature
interface MemoizeOptions<K = string> {
  cache?: Cache<K, unknown>

  maxSize?: number

  ttl?: number
}

On this page