or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.md

index.mddocs/

0

# Memoize One

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: memoize-one

7

- **Package Type**: npm

8

- **Language**: TypeScript

9

- **Installation**: `npm install memoize-one`

10

11

## Core Imports

12

13

```typescript

14

import memoizeOne from "memoize-one";

15

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

16

```

17

18

For CommonJS:

19

20

```javascript

21

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

22

```

23

24

## Basic Usage

25

26

```typescript

27

import memoizeOne from "memoize-one";

28

29

// Simple function memoization

30

function add(a: number, b: number): number {

31

return a + b;

32

}

33

34

const memoizedAdd = memoizeOne(add);

35

36

memoizedAdd(1, 2); // Function called, returns 3

37

memoizedAdd(1, 2); // Cache hit, returns 3 (function not called)

38

memoizedAdd(2, 3); // New arguments, function called, returns 5

39

memoizedAdd(1, 2); // Cache miss (not the latest), function called again

40

41

// Clear cache manually

42

memoizedAdd.clear();

43

```

44

45

## Architecture

46

47

Memoize One uses a simple, memory-efficient architecture:

48

49

- **Single Cache Strategy**: Only stores the most recent function call result, arguments, and context

50

- **Automatic Cache Invalidation**: Previous results are automatically discarded when new arguments are provided

51

- **Context Sensitivity**: Handles `this` context changes by invalidating the cache

52

- **Custom Equality**: Supports custom argument comparison functions for complex data types

53

- **Type Safety**: Full TypeScript support with generic function signature preservation

54

55

## Capabilities

56

57

### Memoization Function

58

59

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

60

61

```typescript { .api }

62

/**

63

* Creates a memoized version of the provided function

64

* @param resultFn - The function to be memoized

65

* @param isEqual - Optional custom equality function for comparing arguments

66

* @returns Memoized function with clear() method

67

*/

68

function memoizeOne<TFunc extends (this: any, ...newArgs: any[]) => any>(

69

resultFn: TFunc,

70

isEqual?: EqualityFn<TFunc>

71

): MemoizedFn<TFunc>;

72

```

73

74

**Usage Examples:**

75

76

```typescript

77

import memoizeOne from "memoize-one";

78

79

// Basic memoization

80

const expensiveCalculation = (x: number, y: number) => {

81

console.log("Computing...");

82

return Math.pow(x, y);

83

};

84

85

const memoized = memoizeOne(expensiveCalculation);

86

memoized(2, 8); // Logs "Computing...", returns 256

87

memoized(2, 8); // No log, returns 256 from cache

88

89

// With custom equality function

90

import isDeepEqual from "lodash.isequal";

91

92

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

93

const memoizedProcess = memoizeOne(processObjects, isDeepEqual);

94

95

memoizedProcess([{ id: 1 }]); // Function called

96

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

97

```

98

99

### Custom Equality Function

100

101

Defines how arguments are compared to determine cache hits.

102

103

```typescript { .api }

104

/**

105

* Function type for custom argument equality comparison

106

* @param newArgs - New function arguments

107

* @param lastArgs - Previously cached arguments

108

* @returns True if arguments are considered equal (cache hit)

109

*/

110

type EqualityFn<TFunc extends (...args: any[]) => any> = (

111

newArgs: Parameters<TFunc>,

112

lastArgs: Parameters<TFunc>

113

) => boolean;

114

```

115

116

**Usage Examples:**

117

118

```typescript

119

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

120

121

// Shallow equality for array contents

122

const shallowArrayEqual: EqualityFn<(arr: number[]) => number> = (newArgs, lastArgs) => {

123

const [newArr] = newArgs;

124

const [lastArr] = lastArgs;

125

return newArr.length === lastArr.length &&

126

newArr.every((val, idx) => val === lastArr[idx]);

127

};

128

129

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

130

const memoizedSum = memoizeOne(sumArray, shallowArrayEqual);

131

132

memoizedSum([1, 2, 3]); // Function called

133

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

134

```

135

136

### Memoized Function Interface

137

138

The enhanced function returned by memoizeOne with additional cache management.

139

140

```typescript { .api }

141

/**

142

* Enhanced function interface with cache management

143

*/

144

type MemoizedFn<TFunc extends (this: any, ...args: any[]) => any> = {

145

/** Clears the cached result and arguments */

146

clear(): void;

147

/** The original function signature with preserved context and types */

148

(this: ThisParameterType<TFunc>, ...args: Parameters<TFunc>): ReturnType<TFunc>;

149

};

150

```

151

152

**Usage Examples:**

153

154

```typescript

155

import memoizeOne from "memoize-one";

156

157

const fibonacci = (n: number): number => {

158

if (n <= 1) return n;

159

return fibonacci(n - 1) + fibonacci(n - 2);

160

};

161

162

const memoizedFib = memoizeOne(fibonacci);

163

164

memoizedFib(10); // Computed

165

memoizedFib(10); // From cache

166

167

// Clear cache when needed

168

memoizedFib.clear();

169

memoizedFib(10); // Computed again

170

171

// Works with context (this)

172

class Calculator {

173

multiplier = 2;

174

175

multiply = memoizeOne((value: number) => {

176

return value * this.multiplier;

177

});

178

}

179

180

const calc = new Calculator();

181

calc.multiply(5); // Returns 10

182

calc.multiply(5); // From cache

183

```

184

185

## Default Equality Behavior

186

187

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

188

189

1. **Argument Count**: Arguments must have the same length

190

2. **Strict Equality**: Each argument uses `===` comparison

191

3. **NaN Special Case**: Two `NaN` values are considered equal (unlike normal `===`)

192

4. **Context Sensitivity**: Changes to `this` context automatically invalidate cache

193

194

**Examples:**

195

196

```typescript

197

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

198

199

// Same arguments - cache hit

200

memoized(1, 2); // Computed

201

memoized(1, 2); // Cache hit

202

203

// Different argument count - cache miss

204

memoized(1, 2, 3); // Computed (different arg count)

205

206

// NaN handling

207

const memoizedNaN = memoizeOne((x) => x);

208

memoizedNaN(NaN); // Computed

209

memoizedNaN(NaN); // Cache hit (NaN === NaN in memoize-one)

210

211

// Object references

212

memoized({ id: 1 }, { id: 2 }); // Computed

213

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

214

```

215

216

## Error Handling

217

218

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

219

220

1. **Exception Propagation**: If the memoized function throws, the memoized function also throws

221

2. **No Caching of Errors**: Thrown results are never cached - each call with arguments that cause an exception will re-execute the function

222

3. **Cache Preservation**: Previous successful cache results remain intact even when exceptions occur

223

224

**Examples:**

225

226

```typescript

227

import memoizeOne from "memoize-one";

228

229

const canThrow = (shouldThrow: boolean, value: number) => {

230

if (shouldThrow) {

231

throw new Error("Something went wrong");

232

}

233

return value * 2;

234

};

235

236

const memoized = memoizeOne(canThrow);

237

238

// Successful call - result cached

239

const result1 = memoized(false, 5); // Returns 10, cached

240

241

// Exception call - no caching

242

try {

243

memoized(true, 3); // Throws Error, not cached

244

} catch (e) {

245

console.log("First error:", e.message);

246

}

247

248

// Same exception call - function called again (no cache)

249

try {

250

memoized(true, 3); // Throws Error again, function re-executed

251

} catch (e) {

252

console.log("Second error:", e.message);

253

}

254

255

// Previous successful result still cached

256

const result2 = memoized(false, 5); // Returns 10 from cache (not re-executed)

257

console.log(result1 === result2); // true

258

```