or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

argument-transformation.mdcache-introspection.mdcache-management.mdcore-memoization.mdequality-comparison.mdindex.mdspecialized-memoization.mdstatistics-profiling.mdutility-methods.md

equality-comparison.mddocs/

0

# Equality and Comparison

1

2

Methods for customizing how arguments and cache keys are compared to determine cache hits, allowing fine-tuned control over memoization behavior.

3

4

## Capabilities

5

6

### Deep Equality

7

8

Use deep equality checking for complex objects and nested data structures.

9

10

```typescript { .api }

11

/**

12

* Deep equality memoization - compares objects and arrays by value recursively

13

* @returns Moizer with deep equality configuration

14

*/

15

deep: Moizer<{ isDeepEqual: true }>;

16

```

17

18

**Usage Examples:**

19

20

```typescript

21

import moize from "moize";

22

23

const processObject = (obj: { a: number; b: { c: string } }) => {

24

return `${obj.a}-${obj.b.c}`;

25

};

26

27

const memoizedProcess = moize.deep(processObject);

28

29

const obj1 = { a: 1, b: { c: "test" } };

30

const obj2 = { a: 1, b: { c: "test" } }; // Different object, same values

31

32

console.log(memoizedProcess(obj1)); // Computed

33

console.log(memoizedProcess(obj2)); // Cached (deep equality match)

34

```

35

36

### Shallow Equality

37

38

Use shallow equality checking for objects with only primitive properties.

39

40

```typescript { .api }

41

/**

42

* Shallow equality memoization - compares object properties at the first level only

43

* @returns Moizer with shallow equality configuration

44

*/

45

shallow: Moizer<{ isShallowEqual: true }>;

46

```

47

48

**Usage Examples:**

49

50

```typescript

51

const processUser = (user: { id: number; name: string; active: boolean }) => {

52

return `User ${user.name} (${user.id}) - ${user.active ? 'active' : 'inactive'}`;

53

};

54

55

const memoizedProcessUser = moize.shallow(processUser);

56

57

const user1 = { id: 1, name: "Alice", active: true };

58

const user2 = { id: 1, name: "Alice", active: true }; // Different object, same properties

59

60

console.log(memoizedProcessUser(user1)); // Computed

61

console.log(memoizedProcessUser(user2)); // Cached (shallow equality match)

62

```

63

64

### Custom Argument Matching

65

66

Provide a custom function to determine if individual arguments are equal.

67

68

```typescript { .api }

69

/**

70

* Custom argument equality matcher

71

* @param argMatcher Function to compare individual arguments

72

* @returns Moizer with custom argument matching

73

*/

74

matchesArg<Matcher extends IsEqual>(argMatcher: Matcher): Moizer<{ matchesArg: Matcher }>;

75

76

type IsEqual = (cacheKeyArg: any, keyArg: any) => boolean;

77

```

78

79

**Usage Examples:**

80

81

```typescript

82

// Case-insensitive string matching

83

const caseInsensitiveEquals = (a: any, b: any) => {

84

if (typeof a === 'string' && typeof b === 'string') {

85

return a.toLowerCase() === b.toLowerCase();

86

}

87

return a === b;

88

};

89

90

const formatName = (name: string) => name.trim().toUpperCase();

91

const memoizedFormatName = moize.matchesArg(caseInsensitiveEquals)(formatName);

92

93

console.log(memoizedFormatName("Alice")); // Computed

94

console.log(memoizedFormatName("ALICE")); // Cached (case-insensitive match)

95

console.log(memoizedFormatName("alice")); // Cached (case-insensitive match)

96

97

// Custom object comparison

98

const compareById = (a: any, b: any) => {

99

if (a && b && typeof a === 'object' && typeof b === 'object') {

100

return a.id === b.id;

101

}

102

return a === b;

103

};

104

105

const processUser = (user: { id: number; name: string }) => `User: ${user.name}`;

106

const memoizedProcessUser = moize.matchesArg(compareById)(processUser);

107

108

console.log(memoizedProcessUser({ id: 1, name: "Alice" })); // Computed

109

console.log(memoizedProcessUser({ id: 1, name: "Bob" })); // Cached (same id)

110

```

111

112

### Custom Key Matching

113

114

Provide a custom function to determine if entire argument arrays (keys) are equal.

115

116

```typescript { .api }

117

/**

118

* Custom key equality matcher

119

* @param keyMatcher Function to compare full argument arrays

120

* @returns Moizer with custom key matching

121

*/

122

matchesKey<Matcher extends IsMatchingKey>(keyMatcher: Matcher): Moizer<{ matchesKey: Matcher }>;

123

124

type IsMatchingKey = (cacheKey: Key, key: Key) => boolean;

125

type Key<Arg extends any = any> = Arg[];

126

```

127

128

**Usage Examples:**

129

130

```typescript

131

// Only compare first two arguments

132

const compareTwoArgs = (cacheKey: any[], key: any[]) => {

133

return cacheKey.length >= 2 && key.length >= 2 &&

134

cacheKey[0] === key[0] && cacheKey[1] === key[1];

135

};

136

137

const calculate = (a: number, b: number, metadata?: any) => a + b;

138

const memoizedCalculate = moize.matchesKey(compareTwoArgs)(calculate);

139

140

console.log(memoizedCalculate(1, 2, { debug: true })); // 3 (computed)

141

console.log(memoizedCalculate(1, 2, { debug: false })); // 3 (cached - metadata ignored)

142

console.log(memoizedCalculate(1, 3, { debug: true })); // 4 (computed - different b)

143

144

// Compare arguments in different order

145

const orderInsensitiveKey = (cacheKey: any[], key: any[]) => {

146

if (cacheKey.length !== key.length) return false;

147

const sortedCache = [...cacheKey].sort();

148

const sortedKey = [...key].sort();

149

return sortedCache.every((val, index) => val === sortedKey[index]);

150

};

151

152

const sum = (...numbers: number[]) => numbers.reduce((a, b) => a + b, 0);

153

const memoizedSum = moize.matchesKey(orderInsensitiveKey)(sum);

154

155

console.log(memoizedSum(1, 2, 3)); // 6 (computed)

156

console.log(memoizedSum(3, 1, 2)); // 6 (cached - same values, different order)

157

```

158

159

### Combining Equality Methods

160

161

Equality methods can be combined with other moize methods through chaining.

162

163

```typescript

164

import moize from "moize";

165

166

const expensiveObjectOperation = (obj: { data: any[] }) => {

167

return obj.data.map(item => item.value).reduce((a, b) => a + b, 0);

168

};

169

170

// Deep equality with size limit and TTL

171

const memoized = moize.deep.maxSize(10).maxAge(5000)(expensiveObjectOperation);

172

173

// Custom equality with profiling

174

const customMemoized = moize

175

.matchesArg((a, b) => JSON.stringify(a) === JSON.stringify(b))

176

.profile('custom-equality')

177

.maxSize(20)(expensiveObjectOperation);

178

```

179

180

### Default Equality Behavior

181

182

Without explicit equality configuration, moize uses reference equality (===) for object comparison and SameValueZero for primitive values.

183

184

```typescript

185

const processArray = (arr: number[]) => arr.reduce((a, b) => a + b, 0);

186

const memoized = moize(processArray);

187

188

const arr1 = [1, 2, 3];

189

const arr2 = [1, 2, 3]; // Different array instance

190

191

console.log(memoized(arr1)); // 6 (computed)

192

console.log(memoized(arr1)); // 6 (cached - same reference)

193

console.log(memoized(arr2)); // 6 (computed - different reference)

194

```