or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

argument-equality.mdindex.mdstatus-rendering.mdtask-management.md
tile.json

argument-equality.mddocs/

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.