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
```