0
# Argument Equality
1
2
Argument comparison utilities for controlling when tasks should re-execute based on changes to their input parameters.
3
4
## Capabilities
5
6
### Shallow Array Equality
7
8
Default equality function that performs shallow comparison of argument arrays.
9
10
```typescript { .api }
11
/**
12
* Compares two argument arrays for shallow equality
13
* Uses notEqual from @lit/reactive-element for individual item comparison
14
* @param oldArgs - Previous arguments array
15
* @param newArgs - Current arguments array
16
* @returns true if arrays have same length and all items are shallowly equal
17
*/
18
function shallowArrayEquals<T extends ReadonlyArray<unknown>>(
19
oldArgs: T,
20
newArgs: T
21
): boolean;
22
```
23
24
**Usage Examples:**
25
26
```typescript
27
import { Task, shallowArrayEquals } from "@lit/task";
28
29
class MyElement extends LitElement {
30
// Default behavior (shallowArrayEquals is used automatically)
31
private _basicTask = new Task(this, {
32
task: async ([name, age]) => fetchUserData(name, age),
33
args: () => [this.userName, this.userAge]
34
// argsEqual defaults to shallowArrayEquals
35
});
36
37
// Explicit shallow comparison
38
private _explicitTask = new Task(this, {
39
task: async ([id, settings]) => updateUser(id, settings),
40
args: () => [this.userId, this.userSettings],
41
argsEqual: shallowArrayEquals
42
});
43
}
44
```
45
46
### Deep Array Equality
47
48
Advanced equality function that performs deep comparison of argument arrays, useful when arguments contain objects.
49
50
```typescript { .api }
51
/**
52
* Compares two argument arrays for deep equality
53
* Recursively compares nested objects, arrays, and primitive values
54
* @param oldArgs - Previous arguments array
55
* @param newArgs - Current arguments array
56
* @returns true if arrays and all nested content are deeply equal
57
*/
58
function deepArrayEquals<T extends ReadonlyArray<unknown>>(
59
oldArgs: T,
60
newArgs: T
61
): boolean;
62
```
63
64
**Usage Examples:**
65
66
```typescript
67
import { Task } from "@lit/task";
68
import { deepArrayEquals } from "@lit/task/deep-equals.js";
69
70
class DataComponent extends LitElement {
71
private _complexTask = new Task(this, {
72
task: async ([filters, options]) => {
73
return searchData(filters, options);
74
},
75
args: () => [
76
{ category: this.category, tags: this.selectedTags },
77
{ sortBy: this.sortField, ascending: this.sortAsc }
78
],
79
// Use deep equality since arguments are objects
80
argsEqual: deepArrayEquals
81
});
82
83
updateFilters(newCategory: string, newTags: string[]) {
84
this.category = newCategory;
85
this.selectedTags = [...newTags];
86
// Task will re-run because deepArrayEquals detects the change
87
}
88
}
89
```
90
91
### Deep Object Equality
92
93
Core deep equality function for comparing individual values recursively.
94
95
```typescript { .api }
96
/**
97
* Recursively compares two values for deep equality
98
* Handles primitives, objects, arrays, Maps, Sets, RegExps, and custom valueOf/toString
99
* @param a - First value to compare
100
* @param b - Second value to compare
101
* @returns true if values are deeply equal
102
*/
103
function deepEquals(a: unknown, b: unknown): boolean;
104
```
105
106
**Supported Types:**
107
- Primitives (compared with Object.is())
108
- Objects (same constructor, same properties, recursively equal values)
109
- Arrays (same length, recursively equal items)
110
- Maps and Sets (same size, recursively equal entries/keys)
111
- RegExp (same source and flags)
112
- Objects with custom valueOf() (e.g., Date)
113
- Objects with custom toString() (e.g., URL)
114
115
**Usage Examples:**
116
117
```typescript
118
import { deepEquals } from "@lit/task/deep-equals.js";
119
120
// Custom equality function using deepEquals
121
class CustomComponent extends LitElement {
122
private _advancedTask = new Task(this, {
123
task: async ([config]) => processConfig(config),
124
args: () => [this.configuration],
125
argsEqual: (oldArgs, newArgs) => {
126
// Custom logic: only check the 'important' field deeply
127
return deepEquals(oldArgs[0]?.important, newArgs[0]?.important);
128
}
129
});
130
}
131
132
// Testing equality manually
133
const config1 = {
134
settings: { theme: 'dark', lang: 'en' },
135
metadata: new Date('2023-01-01')
136
};
137
const config2 = {
138
settings: { theme: 'dark', lang: 'en' },
139
metadata: new Date('2023-01-01')
140
};
141
142
console.log(deepEquals(config1, config2)); // true
143
```
144
145
### Custom Equality Functions
146
147
Creating custom argument comparison functions for specific use cases.
148
149
**Performance-Optimized Equality:**
150
151
```typescript
152
class OptimizedComponent extends LitElement {
153
private _optimizedTask = new Task(this, {
154
task: async ([userId, prefs]) => loadUserPreferences(userId, prefs),
155
args: () => [this.userId, this.userPreferences],
156
// Only check userId, ignore preferences changes
157
argsEqual: (oldArgs, newArgs) => oldArgs[0] === newArgs[0]
158
});
159
}
160
```
161
162
**Selective Deep Comparison:**
163
164
```typescript
165
class SelectiveComponent extends LitElement {
166
private _selectiveTask = new Task(this, {
167
task: async ([query, filters, pagination]) => searchAPI(query, filters, pagination),
168
args: () => [this.searchQuery, this.activeFilters, this.paginationState],
169
argsEqual: (oldArgs, newArgs) => {
170
// Shallow check query and deep check filters, ignore pagination
171
return oldArgs[0] === newArgs[0] &&
172
deepEquals(oldArgs[1], newArgs[1]);
173
}
174
});
175
}
176
```
177
178
**Debounced Equality:**
179
180
```typescript
181
class DebouncedComponent extends LitElement {
182
private _lastChangeTime = 0;
183
private _debounceMs = 300;
184
185
private _debouncedTask = new Task(this, {
186
task: async ([searchTerm]) => searchAPI(searchTerm),
187
args: () => [this.searchInput],
188
argsEqual: (oldArgs, newArgs) => {
189
const now = Date.now();
190
if (oldArgs[0] !== newArgs[0]) {
191
this._lastChangeTime = now;
192
return true; // Consider equal to prevent immediate execution
193
}
194
// Only execute if enough time has passed
195
return (now - this._lastChangeTime) < this._debounceMs;
196
}
197
});
198
}
199
```
200
201
### Important Notes
202
203
**Cycle Detection:**
204
The `deepEquals` function does not handle circular references. Objects must be cycle-free or the function will run infinitely.
205
206
**Performance Considerations:**
207
- `shallowArrayEquals`: Fast, suitable for primitive arguments
208
- `deepArrayEquals`: Slower, use when arguments contain objects
209
- Custom functions: Tailor performance to your specific needs
210
211
**Type Safety:**
212
All equality functions maintain full TypeScript type safety with the argument arrays.