fast-equals 5.0.0-beta.6 → 5.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # fast-equals CHANGELOG
2
2
 
3
+ ## 5.0.1
4
+
5
+ ### Bugfixes
6
+
7
+ - Fix reference to `metaOverride` in typings and documentation (holdover from temporary API in v5 beta)
8
+
3
9
  ## 5.0.0
4
10
 
5
11
  ### Breaking changes
@@ -24,6 +30,10 @@ To better facilitate strict comparisons, but also to allow for `meta` use separa
24
30
 
25
31
  You can create a custom circular equality comparator through `createCustomEqual` now by providing `circular: true` to the options.
26
32
 
33
+ #### Custom `meta` values are no longer passed at callsite
34
+
35
+ To use `meta` properties for comparisons, they must be returned in a `createState` method.
36
+
27
37
  #### Deep links have changed
28
38
 
29
39
  If you were deep-linking into a specific asset type (ESM / CJS / UMD), they have changed location.
package/README.md CHANGED
@@ -165,6 +165,7 @@ console.log(circularShallowEqual(array, [array])); // false
165
165
 
166
166
  Performs the same comparison as `deepEqual` but performs a strict comparison of the objects. In this includes:
167
167
 
168
+ - Checking symbol properties
168
169
  - Checking non-enumerable properties in object comparisons
169
170
  - Checking full descriptor of properties on the object to match
170
171
  - Checking non-index properties on arrays
@@ -309,7 +310,7 @@ function createCustomEqual<Meta>(options: {
309
310
  ) => boolean;
310
311
  createState?: () => { cache?: Cache; meta?: Meta };
311
312
  strict?: boolean;
312
- }): <A, B>(a: A, b: B, metaOverride?: Meta) => boolean;
313
+ }): <A, B>(a: A, b: B) => boolean;
313
314
  ```
314
315
 
315
316
  Create a custom equality comparator. This allows complete control over building a bespoke equality method, in case your use-case requires a higher degree of performance, legacy environment support, or any other non-standard usage. The [recipes](#recipes) provide examples of use in different use-cases, but if you have a specific goal in mind and would like assistance feel free to [file an issue](https://github.com/planttheidea/fast-equals/issues).
@@ -329,7 +330,7 @@ Some recipes have been created to provide examples of use-cases for `createCusto
329
330
 
330
331
  ## Benchmarks
331
332
 
332
- All benchmarks were performed on an i7-8650U Ubuntu Linux laptop with 24GB of memory using NodeJS version `12.19.1`, and are based on averages of running comparisons based deep equality on the following object types:
333
+ All benchmarks were performed on an i9-11900H Ubuntu Linux 22.04 laptop with 64GB of memory using NodeJS version `16.14.2`, and are based on averages of running comparisons based deep equality on the following object types:
333
334
 
334
335
  - Primitives (`String`, `Number`, `null`, `undefined`)
335
336
  - `Function`
@@ -340,23 +341,47 @@ All benchmarks were performed on an i7-8650U Ubuntu Linux laptop with 24GB of me
340
341
  - `react` elements
341
342
  - A mixed object with a combination of all the above types
342
343
 
343
- | | Operations / second |
344
- | -------------------------- | ------------------- |
345
- | **fast-equals** | **153,880** |
346
- | fast-deep-equal | 144,035 |
347
- | react-fast-compare | 130,324 |
348
- | nano-equal | 104,624 |
349
- | **fast-equals (circular)** | **97,610** |
350
- | shallow-equal-fuzzy | 83,946 |
351
- | underscore.isEqual | 47,370 |
352
- | lodash.isEqual | 25,053 |
353
- | deep-eql | 22,146 |
354
- | assert.deepStrictEqual | 532 |
355
- | deep-equal | 209 |
344
+ ```bash
345
+ Testing mixed objects equal...
346
+ ┌─────────┬─────────────────────────────────┬────────────────┐
347
+ (index) Package │ Ops/sec │
348
+ ├─────────┼─────────────────────────────────┼────────────────┤
349
+ │ 0 │ 'fast-equals' │ 1249567.730326 │
350
+ │ 1 │ 'fast-deep-equal' │ 1182463.587514
351
+ │ 2 │ 'react-fast-compare' │ 1152487.319161 │
352
+ │ 3 │ 'shallow-equal-fuzzy' │ 1092360.712389
353
+ │ 4 │ 'fast-equals (circular)' │ 676669.92003 │
354
+ │ 5 │ 'underscore.isEqual' │ 429430.837497 │
355
+ │ 6 │ 'lodash.isEqual' │ 237915.684734 │
356
+ │ 7 │ 'fast-equals (strict)' │ 181386.38032 │
357
+ │ 8 │ 'fast-equals (strict circular)' │ 156779.745875 │
358
+ │ 9 │ 'deep-eql' │ 139155.099209 │
359
+ │ 10 │ 'deep-equal' │ 1026.527229 │
360
+ └─────────┴─────────────────────────────────┴────────────────┘
361
+
362
+ Testing mixed objects not equal...
363
+ ┌─────────┬─────────────────────────────────┬────────────────┐
364
+ │ (index) │ Package │ Ops/sec │
365
+ ├─────────┼─────────────────────────────────┼────────────────┤
366
+ │ 0 │ 'fast-equals' │ 3255824.097237 │
367
+ │ 1 │ 'react-fast-compare' │ 2654721.726058 │
368
+ │ 2 │ 'fast-deep-equal' │ 2582218.974752 │
369
+ │ 3 │ 'fast-equals (circular)' │ 2474303.26566 │
370
+ │ 4 │ 'fast-equals (strict)' │ 1088066.604881 │
371
+ │ 5 │ 'fast-equals (strict circular)' │ 949253.614181 │
372
+ │ 6 │ 'nano-equal' │ 939170.554148 │
373
+ │ 7 │ 'underscore.isEqual' │ 738852.197879 │
374
+ │ 8 │ 'lodash.isEqual' │ 307306.622212 │
375
+ │ 9 │ 'deep-eql' │ 156250.110401 │
376
+ │ 10 │ 'assert.deepStrictEqual' │ 22839.454561 │
377
+ │ 11 │ 'deep-equal' │ 4034.45114 │
378
+ └─────────┴─────────────────────────────────┴────────────────┘
379
+ ```
356
380
 
357
381
  Caveats that impact the benchmark (and accuracy of comparison):
358
382
 
359
383
  - `Map`s, `Promise`s, and `Set`s were excluded from the benchmark entirely because no library other than `deep-eql` fully supported their comparison
384
+ - `fast-deep-equal`, `react-fast-compare` and `nano-equal` throw on objects with `null` as prototype (`Object.create(null)`)
360
385
  - `assert.deepStrictEqual` does not support `NaN` or `SameValueZero` equality for dates
361
386
  - `deep-eql` does not support `SameValueZero` equality for zero equality (positive and negative zero are not equal)
362
387
  - `deep-equal` does not support `NaN` and does not strictly compare object type, or date / regexp values, nor uses `SameValueZero` equality for dates
@@ -1,12 +1,30 @@
1
+ /**
2
+ * Cache used to store references to objects, used for circular
3
+ * reference checks.
4
+ */
1
5
  export interface Cache<Key extends object, Value> {
2
6
  delete(key: Key): boolean;
3
7
  get(key: Key): Value | undefined;
4
8
  set(key: Key, value: any): any;
5
9
  }
6
10
  export interface State<Meta> {
11
+ /**
12
+ * Cache used to identify circular references
13
+ */
7
14
  readonly cache: Cache<any, any> | undefined;
15
+ /**
16
+ * Method used to determine equality of nested value.
17
+ */
8
18
  readonly equals: InternalEqualityComparator<Meta>;
19
+ /**
20
+ * Additional value that can be used for comparisons.
21
+ */
9
22
  meta: Meta;
23
+ /**
24
+ * Whether the equality comparison is strict, meaning it matches
25
+ * all properties (including symbols and non-enumerable properties)
26
+ * with equal shape of descriptors.
27
+ */
10
28
  readonly strict: boolean;
11
29
  }
12
30
  export interface CircularState<Meta> extends State<Meta> {
@@ -20,13 +38,42 @@ export interface Dictionary<Value = any> {
20
38
  $$typeof?: any;
21
39
  }
22
40
  export interface ComparatorConfig<Meta> {
41
+ /**
42
+ * Whether the arrays passed are equal in value. In strict mode, this includes
43
+ * additional properties added to the array.
44
+ */
23
45
  areArraysEqual: TypeEqualityComparator<any, Meta>;
46
+ /**
47
+ * Whether the dates passed are equal in value.
48
+ */
24
49
  areDatesEqual: TypeEqualityComparator<any, Meta>;
50
+ /**
51
+ * Whether the maps passed are equal in value. In strict mode, this includes
52
+ * additional properties added to the map.
53
+ */
25
54
  areMapsEqual: TypeEqualityComparator<any, Meta>;
55
+ /**
56
+ * Whether the objects passed are equal in value. In strict mode, this includes
57
+ * non-enumerable properties added to the map, as well as symbol properties.
58
+ */
26
59
  areObjectsEqual: TypeEqualityComparator<any, Meta>;
60
+ /**
61
+ * Whether the primitive wrappers passed are equal in value.
62
+ */
27
63
  arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
64
+ /**
65
+ * Whether the regexps passed are equal in value.
66
+ */
28
67
  areRegExpsEqual: TypeEqualityComparator<any, Meta>;
68
+ /**
69
+ * Whether the sets passed are equal in value. In strict mode, this includes
70
+ * additional properties added to the set.
71
+ */
29
72
  areSetsEqual: TypeEqualityComparator<any, Meta>;
73
+ /**
74
+ * Whether the typed arrays passed are equal in value. In strict mode, this includes
75
+ * additional properties added to the typed array.
76
+ */
30
77
  areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
31
78
  }
32
79
  export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
@@ -39,12 +86,49 @@ export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) =
39
86
  export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
40
87
  export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
41
88
  export type PrimitiveWrapper = Boolean | Number | String;
89
+ /**
90
+ * Type which encompasses possible instances of TypedArray
91
+ * classes.
92
+ *
93
+ * **NOTE**: This does not include `BigInt64Array` and
94
+ * `BitUint64Array` because those are part of ES2020 and
95
+ * not supported by certain TS configurations. If using
96
+ * either in `areTypedArraysEqual`, you can cast the
97
+ * instance as `TypedArray` and it will work as expected,
98
+ * because runtime checks will still work for those classes.
99
+ */
42
100
  export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
43
101
  export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
44
102
  export interface CustomEqualCreatorOptions<Meta> {
103
+ /**
104
+ * Whether circular references should be supported. It causes the
105
+ * comparison to be slower, but for objects that have circular references
106
+ * it is required to avoid stack overflows.
107
+ */
45
108
  circular?: boolean;
109
+ /**
110
+ * Create a custom configuration of type-specific equality comparators.
111
+ * This receives the default configuration, which allows either replacement
112
+ * or supersetting of the default methods.
113
+ */
46
114
  createCustomConfig?: CreateCustomComparatorConfig<Meta>;
115
+ /**
116
+ * Create a custom internal comparator, which is used as an override to the
117
+ * default entry point for nested value equality comparisons. This is often
118
+ * used for doing custom logic for specific types (such as handling a specific
119
+ * class instance differently than other objects) or to incorporate `meta` in
120
+ * the comparison. See the recipes for examples.
121
+ */
47
122
  createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
123
+ /**
124
+ * Create a custom `state` object passed between the methods. This allows for
125
+ * custom `cache` and/or `meta` values to be used.
126
+ */
48
127
  createState?: CreateState<Meta>;
128
+ /**
129
+ * Whether the equality comparison is strict, meaning it matches
130
+ * all properties (including symbols and non-enumerable properties)
131
+ * with equal shape of descriptors.
132
+ */
49
133
  strict?: boolean;
50
134
  }
@@ -1,12 +1,30 @@
1
+ /**
2
+ * Cache used to store references to objects, used for circular
3
+ * reference checks.
4
+ */
1
5
  export interface Cache<Key extends object, Value> {
2
6
  delete(key: Key): boolean;
3
7
  get(key: Key): Value | undefined;
4
8
  set(key: Key, value: any): any;
5
9
  }
6
10
  export interface State<Meta> {
11
+ /**
12
+ * Cache used to identify circular references
13
+ */
7
14
  readonly cache: Cache<any, any> | undefined;
15
+ /**
16
+ * Method used to determine equality of nested value.
17
+ */
8
18
  readonly equals: InternalEqualityComparator<Meta>;
19
+ /**
20
+ * Additional value that can be used for comparisons.
21
+ */
9
22
  meta: Meta;
23
+ /**
24
+ * Whether the equality comparison is strict, meaning it matches
25
+ * all properties (including symbols and non-enumerable properties)
26
+ * with equal shape of descriptors.
27
+ */
10
28
  readonly strict: boolean;
11
29
  }
12
30
  export interface CircularState<Meta> extends State<Meta> {
@@ -20,13 +38,42 @@ export interface Dictionary<Value = any> {
20
38
  $$typeof?: any;
21
39
  }
22
40
  export interface ComparatorConfig<Meta> {
41
+ /**
42
+ * Whether the arrays passed are equal in value. In strict mode, this includes
43
+ * additional properties added to the array.
44
+ */
23
45
  areArraysEqual: TypeEqualityComparator<any, Meta>;
46
+ /**
47
+ * Whether the dates passed are equal in value.
48
+ */
24
49
  areDatesEqual: TypeEqualityComparator<any, Meta>;
50
+ /**
51
+ * Whether the maps passed are equal in value. In strict mode, this includes
52
+ * additional properties added to the map.
53
+ */
25
54
  areMapsEqual: TypeEqualityComparator<any, Meta>;
55
+ /**
56
+ * Whether the objects passed are equal in value. In strict mode, this includes
57
+ * non-enumerable properties added to the map, as well as symbol properties.
58
+ */
26
59
  areObjectsEqual: TypeEqualityComparator<any, Meta>;
60
+ /**
61
+ * Whether the primitive wrappers passed are equal in value.
62
+ */
27
63
  arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
64
+ /**
65
+ * Whether the regexps passed are equal in value.
66
+ */
28
67
  areRegExpsEqual: TypeEqualityComparator<any, Meta>;
68
+ /**
69
+ * Whether the sets passed are equal in value. In strict mode, this includes
70
+ * additional properties added to the set.
71
+ */
29
72
  areSetsEqual: TypeEqualityComparator<any, Meta>;
73
+ /**
74
+ * Whether the typed arrays passed are equal in value. In strict mode, this includes
75
+ * additional properties added to the typed array.
76
+ */
30
77
  areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
31
78
  }
32
79
  export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
@@ -39,12 +86,49 @@ export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) =
39
86
  export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
40
87
  export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
41
88
  export type PrimitiveWrapper = Boolean | Number | String;
89
+ /**
90
+ * Type which encompasses possible instances of TypedArray
91
+ * classes.
92
+ *
93
+ * **NOTE**: This does not include `BigInt64Array` and
94
+ * `BitUint64Array` because those are part of ES2020 and
95
+ * not supported by certain TS configurations. If using
96
+ * either in `areTypedArraysEqual`, you can cast the
97
+ * instance as `TypedArray` and it will work as expected,
98
+ * because runtime checks will still work for those classes.
99
+ */
42
100
  export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
43
101
  export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
44
102
  export interface CustomEqualCreatorOptions<Meta> {
103
+ /**
104
+ * Whether circular references should be supported. It causes the
105
+ * comparison to be slower, but for objects that have circular references
106
+ * it is required to avoid stack overflows.
107
+ */
45
108
  circular?: boolean;
109
+ /**
110
+ * Create a custom configuration of type-specific equality comparators.
111
+ * This receives the default configuration, which allows either replacement
112
+ * or supersetting of the default methods.
113
+ */
46
114
  createCustomConfig?: CreateCustomComparatorConfig<Meta>;
115
+ /**
116
+ * Create a custom internal comparator, which is used as an override to the
117
+ * default entry point for nested value equality comparisons. This is often
118
+ * used for doing custom logic for specific types (such as handling a specific
119
+ * class instance differently than other objects) or to incorporate `meta` in
120
+ * the comparison. See the recipes for examples.
121
+ */
47
122
  createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
123
+ /**
124
+ * Create a custom `state` object passed between the methods. This allows for
125
+ * custom `cache` and/or `meta` values to be used.
126
+ */
48
127
  createState?: CreateState<Meta>;
128
+ /**
129
+ * Whether the equality comparison is strict, meaning it matches
130
+ * all properties (including symbols and non-enumerable properties)
131
+ * with equal shape of descriptors.
132
+ */
49
133
  strict?: boolean;
50
134
  }
@@ -1,12 +1,30 @@
1
+ /**
2
+ * Cache used to store references to objects, used for circular
3
+ * reference checks.
4
+ */
1
5
  export interface Cache<Key extends object, Value> {
2
6
  delete(key: Key): boolean;
3
7
  get(key: Key): Value | undefined;
4
8
  set(key: Key, value: any): any;
5
9
  }
6
10
  export interface State<Meta> {
11
+ /**
12
+ * Cache used to identify circular references
13
+ */
7
14
  readonly cache: Cache<any, any> | undefined;
15
+ /**
16
+ * Method used to determine equality of nested value.
17
+ */
8
18
  readonly equals: InternalEqualityComparator<Meta>;
19
+ /**
20
+ * Additional value that can be used for comparisons.
21
+ */
9
22
  meta: Meta;
23
+ /**
24
+ * Whether the equality comparison is strict, meaning it matches
25
+ * all properties (including symbols and non-enumerable properties)
26
+ * with equal shape of descriptors.
27
+ */
10
28
  readonly strict: boolean;
11
29
  }
12
30
  export interface CircularState<Meta> extends State<Meta> {
@@ -20,13 +38,42 @@ export interface Dictionary<Value = any> {
20
38
  $$typeof?: any;
21
39
  }
22
40
  export interface ComparatorConfig<Meta> {
41
+ /**
42
+ * Whether the arrays passed are equal in value. In strict mode, this includes
43
+ * additional properties added to the array.
44
+ */
23
45
  areArraysEqual: TypeEqualityComparator<any, Meta>;
46
+ /**
47
+ * Whether the dates passed are equal in value.
48
+ */
24
49
  areDatesEqual: TypeEqualityComparator<any, Meta>;
50
+ /**
51
+ * Whether the maps passed are equal in value. In strict mode, this includes
52
+ * additional properties added to the map.
53
+ */
25
54
  areMapsEqual: TypeEqualityComparator<any, Meta>;
55
+ /**
56
+ * Whether the objects passed are equal in value. In strict mode, this includes
57
+ * non-enumerable properties added to the map, as well as symbol properties.
58
+ */
26
59
  areObjectsEqual: TypeEqualityComparator<any, Meta>;
60
+ /**
61
+ * Whether the primitive wrappers passed are equal in value.
62
+ */
27
63
  arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
64
+ /**
65
+ * Whether the regexps passed are equal in value.
66
+ */
28
67
  areRegExpsEqual: TypeEqualityComparator<any, Meta>;
68
+ /**
69
+ * Whether the sets passed are equal in value. In strict mode, this includes
70
+ * additional properties added to the set.
71
+ */
29
72
  areSetsEqual: TypeEqualityComparator<any, Meta>;
73
+ /**
74
+ * Whether the typed arrays passed are equal in value. In strict mode, this includes
75
+ * additional properties added to the typed array.
76
+ */
30
77
  areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
31
78
  }
32
79
  export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
@@ -39,12 +86,49 @@ export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) =
39
86
  export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
40
87
  export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
41
88
  export type PrimitiveWrapper = Boolean | Number | String;
89
+ /**
90
+ * Type which encompasses possible instances of TypedArray
91
+ * classes.
92
+ *
93
+ * **NOTE**: This does not include `BigInt64Array` and
94
+ * `BitUint64Array` because those are part of ES2020 and
95
+ * not supported by certain TS configurations. If using
96
+ * either in `areTypedArraysEqual`, you can cast the
97
+ * instance as `TypedArray` and it will work as expected,
98
+ * because runtime checks will still work for those classes.
99
+ */
42
100
  export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
43
101
  export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
44
102
  export interface CustomEqualCreatorOptions<Meta> {
103
+ /**
104
+ * Whether circular references should be supported. It causes the
105
+ * comparison to be slower, but for objects that have circular references
106
+ * it is required to avoid stack overflows.
107
+ */
45
108
  circular?: boolean;
109
+ /**
110
+ * Create a custom configuration of type-specific equality comparators.
111
+ * This receives the default configuration, which allows either replacement
112
+ * or supersetting of the default methods.
113
+ */
46
114
  createCustomConfig?: CreateCustomComparatorConfig<Meta>;
115
+ /**
116
+ * Create a custom internal comparator, which is used as an override to the
117
+ * default entry point for nested value equality comparisons. This is often
118
+ * used for doing custom logic for specific types (such as handling a specific
119
+ * class instance differently than other objects) or to incorporate `meta` in
120
+ * the comparison. See the recipes for examples.
121
+ */
47
122
  createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
123
+ /**
124
+ * Create a custom `state` object passed between the methods. This allows for
125
+ * custom `cache` and/or `meta` values to be used.
126
+ */
48
127
  createState?: CreateState<Meta>;
128
+ /**
129
+ * Whether the equality comparison is strict, meaning it matches
130
+ * all properties (including symbols and non-enumerable properties)
131
+ * with equal shape of descriptors.
132
+ */
49
133
  strict?: boolean;
50
134
  }
@@ -1,12 +1,30 @@
1
+ /**
2
+ * Cache used to store references to objects, used for circular
3
+ * reference checks.
4
+ */
1
5
  export interface Cache<Key extends object, Value> {
2
6
  delete(key: Key): boolean;
3
7
  get(key: Key): Value | undefined;
4
8
  set(key: Key, value: any): any;
5
9
  }
6
10
  export interface State<Meta> {
11
+ /**
12
+ * Cache used to identify circular references
13
+ */
7
14
  readonly cache: Cache<any, any> | undefined;
15
+ /**
16
+ * Method used to determine equality of nested value.
17
+ */
8
18
  readonly equals: InternalEqualityComparator<Meta>;
19
+ /**
20
+ * Additional value that can be used for comparisons.
21
+ */
9
22
  meta: Meta;
23
+ /**
24
+ * Whether the equality comparison is strict, meaning it matches
25
+ * all properties (including symbols and non-enumerable properties)
26
+ * with equal shape of descriptors.
27
+ */
10
28
  readonly strict: boolean;
11
29
  }
12
30
  export interface CircularState<Meta> extends State<Meta> {
@@ -20,13 +38,42 @@ export interface Dictionary<Value = any> {
20
38
  $$typeof?: any;
21
39
  }
22
40
  export interface ComparatorConfig<Meta> {
41
+ /**
42
+ * Whether the arrays passed are equal in value. In strict mode, this includes
43
+ * additional properties added to the array.
44
+ */
23
45
  areArraysEqual: TypeEqualityComparator<any, Meta>;
46
+ /**
47
+ * Whether the dates passed are equal in value.
48
+ */
24
49
  areDatesEqual: TypeEqualityComparator<any, Meta>;
50
+ /**
51
+ * Whether the maps passed are equal in value. In strict mode, this includes
52
+ * additional properties added to the map.
53
+ */
25
54
  areMapsEqual: TypeEqualityComparator<any, Meta>;
55
+ /**
56
+ * Whether the objects passed are equal in value. In strict mode, this includes
57
+ * non-enumerable properties added to the map, as well as symbol properties.
58
+ */
26
59
  areObjectsEqual: TypeEqualityComparator<any, Meta>;
60
+ /**
61
+ * Whether the primitive wrappers passed are equal in value.
62
+ */
27
63
  arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
64
+ /**
65
+ * Whether the regexps passed are equal in value.
66
+ */
28
67
  areRegExpsEqual: TypeEqualityComparator<any, Meta>;
68
+ /**
69
+ * Whether the sets passed are equal in value. In strict mode, this includes
70
+ * additional properties added to the set.
71
+ */
29
72
  areSetsEqual: TypeEqualityComparator<any, Meta>;
73
+ /**
74
+ * Whether the typed arrays passed are equal in value. In strict mode, this includes
75
+ * additional properties added to the typed array.
76
+ */
30
77
  areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
31
78
  }
32
79
  export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
@@ -39,12 +86,49 @@ export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) =
39
86
  export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
40
87
  export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
41
88
  export type PrimitiveWrapper = Boolean | Number | String;
89
+ /**
90
+ * Type which encompasses possible instances of TypedArray
91
+ * classes.
92
+ *
93
+ * **NOTE**: This does not include `BigInt64Array` and
94
+ * `BitUint64Array` because those are part of ES2020 and
95
+ * not supported by certain TS configurations. If using
96
+ * either in `areTypedArraysEqual`, you can cast the
97
+ * instance as `TypedArray` and it will work as expected,
98
+ * because runtime checks will still work for those classes.
99
+ */
42
100
  export type TypedArray = Float32Array | Float64Array | Int8Array | Int16Array | Int32Array | Uint16Array | Uint32Array | Uint8Array | Uint8ClampedArray;
43
101
  export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
44
102
  export interface CustomEqualCreatorOptions<Meta> {
103
+ /**
104
+ * Whether circular references should be supported. It causes the
105
+ * comparison to be slower, but for objects that have circular references
106
+ * it is required to avoid stack overflows.
107
+ */
45
108
  circular?: boolean;
109
+ /**
110
+ * Create a custom configuration of type-specific equality comparators.
111
+ * This receives the default configuration, which allows either replacement
112
+ * or supersetting of the default methods.
113
+ */
46
114
  createCustomConfig?: CreateCustomComparatorConfig<Meta>;
115
+ /**
116
+ * Create a custom internal comparator, which is used as an override to the
117
+ * default entry point for nested value equality comparisons. This is often
118
+ * used for doing custom logic for specific types (such as handling a specific
119
+ * class instance differently than other objects) or to incorporate `meta` in
120
+ * the comparison. See the recipes for examples.
121
+ */
47
122
  createInternalComparator?: (compare: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
123
+ /**
124
+ * Create a custom `state` object passed between the methods. This allows for
125
+ * custom `cache` and/or `meta` values to be used.
126
+ */
48
127
  createState?: CreateState<Meta>;
128
+ /**
129
+ * Whether the equality comparison is strict, meaning it matches
130
+ * all properties (including symbols and non-enumerable properties)
131
+ * with equal shape of descriptors.
132
+ */
49
133
  strict?: boolean;
50
134
  }
package/index.d.ts CHANGED
@@ -46,9 +46,9 @@ export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
46
46
  *
47
47
  * This can be done to create very targeted comparisons in extreme hot-path scenarios
48
48
  * where the standard methods are not performant enough, but can also be used to provide
49
- * support for legacy environments that do not support expected features like
50
- * `RegExp.prototype.flags` out of the box.
49
+ * support for legacy environments that cannot polyfill for modern features expected by
50
+ * `fast-equals`, such as `WeakMap` or `RegExp.prototype.flags`.
51
51
  */
52
- export declare function createCustomEqual<Meta>(
52
+ export declare function createCustomEqual<Meta = undefined>(
53
53
  options?: CustomEqualCreatorOptions<Meta>,
54
- ): <A, B>(a: A, b: B, metaOverride?: Meta) => boolean;
54
+ ): <A, B>(a: A, b: B) => boolean;
package/package.json CHANGED
@@ -11,43 +11,43 @@
11
11
  "@rollup/plugin-replace": "^5.0.2",
12
12
  "@rollup/plugin-terser": "^0.4.0",
13
13
  "@rollup/plugin-typescript": "^11.0.0",
14
- "@types/jest": "^29.2.5",
14
+ "@types/jest": "^29.5.0",
15
15
  "@types/lodash": "^4.14.184",
16
- "@types/node": "^18.14.2",
16
+ "@types/node": "^18.15.3",
17
17
  "@types/ramda": "^0.28.23",
18
18
  "@types/react": "^18.0.28",
19
19
  "@types/react-dom": "^18.0.11",
20
- "@typescript-eslint/eslint-plugin": "^5.54.0",
21
- "@typescript-eslint/parser": "^5.54.0",
20
+ "@typescript-eslint/eslint-plugin": "^5.55.0",
21
+ "@typescript-eslint/parser": "^5.55.0",
22
22
  "decircularize": "^1.0.0",
23
23
  "deep-eql": "^4.1.0",
24
24
  "deep-equal": "^2.0.5",
25
- "eslint": "^8.35.0",
25
+ "eslint": "^8.36.0",
26
26
  "eslint-friendly-formatter": "^4.0.1",
27
27
  "eslint-webpack-plugin": "^4.0.0",
28
28
  "fast-deep-equal": "^3.1.3",
29
29
  "html-webpack-plugin": "^5.5.0",
30
30
  "in-publish": "^2.0.0",
31
- "jest": "^29.4.3",
32
- "jest-environment-jsdom": "^29.4.3",
31
+ "jest": "^29.5.0",
32
+ "jest-environment-jsdom": "^29.5.0",
33
33
  "jest-expect-message": "^1.1.3",
34
34
  "lodash": "^4.17.21",
35
35
  "nano-equal": "^2.0.2",
36
36
  "prettier": "^2.8.4",
37
37
  "react": "^18.2.0",
38
38
  "react-dom": "^18.2.0",
39
- "react-fast-compare": "^3.2.0",
40
- "release-it": "^15.6.1",
41
- "rollup": "^3.17.3",
39
+ "react-fast-compare": "^3.2.1",
40
+ "release-it": "^15.9.0",
41
+ "rollup": "^3.19.1",
42
42
  "shallow-equal-fuzzy": "^0.0.2",
43
- "tinybench": "^2.3.1",
43
+ "tinybench": "^2.4.0",
44
44
  "ts-jest": "^29.0.3",
45
45
  "ts-loader": "^9.4.2",
46
46
  "typescript": "^4.9.5",
47
47
  "underscore": "^1.13.4",
48
- "webpack": "^5.75.0",
48
+ "webpack": "^5.76.2",
49
49
  "webpack-cli": "^5.0.1",
50
- "webpack-dev-server": "^4.11.1"
50
+ "webpack-dev-server": "^4.13.0"
51
51
  },
52
52
  "engines": {
53
53
  "node": ">=6.0.0"
@@ -109,5 +109,5 @@
109
109
  "sideEffects": false,
110
110
  "type": "module",
111
111
  "types": "./index.d.ts",
112
- "version": "5.0.0-beta.6"
112
+ "version": "5.0.1"
113
113
  }
@@ -1,3 +1,7 @@
1
+ /**
2
+ * Cache used to store references to objects, used for circular
3
+ * reference checks.
4
+ */
1
5
  export interface Cache<Key extends object, Value> {
2
6
  delete(key: Key): boolean;
3
7
  get(key: Key): Value | undefined;
@@ -5,9 +9,23 @@ export interface Cache<Key extends object, Value> {
5
9
  }
6
10
 
7
11
  export interface State<Meta> {
12
+ /**
13
+ * Cache used to identify circular references
14
+ */
8
15
  readonly cache: Cache<any, any> | undefined;
16
+ /**
17
+ * Method used to determine equality of nested value.
18
+ */
9
19
  readonly equals: InternalEqualityComparator<Meta>;
20
+ /**
21
+ * Additional value that can be used for comparisons.
22
+ */
10
23
  meta: Meta;
24
+ /**
25
+ * Whether the equality comparison is strict, meaning it matches
26
+ * all properties (including symbols and non-enumerable properties)
27
+ * with equal shape of descriptors.
28
+ */
11
29
  readonly strict: boolean;
12
30
  }
13
31
 
@@ -25,13 +43,42 @@ export interface Dictionary<Value = any> {
25
43
  }
26
44
 
27
45
  export interface ComparatorConfig<Meta> {
46
+ /**
47
+ * Whether the arrays passed are equal in value. In strict mode, this includes
48
+ * additional properties added to the array.
49
+ */
28
50
  areArraysEqual: TypeEqualityComparator<any, Meta>;
51
+ /**
52
+ * Whether the dates passed are equal in value.
53
+ */
29
54
  areDatesEqual: TypeEqualityComparator<any, Meta>;
55
+ /**
56
+ * Whether the maps passed are equal in value. In strict mode, this includes
57
+ * additional properties added to the map.
58
+ */
30
59
  areMapsEqual: TypeEqualityComparator<any, Meta>;
60
+ /**
61
+ * Whether the objects passed are equal in value. In strict mode, this includes
62
+ * non-enumerable properties added to the map, as well as symbol properties.
63
+ */
31
64
  areObjectsEqual: TypeEqualityComparator<any, Meta>;
65
+ /**
66
+ * Whether the primitive wrappers passed are equal in value.
67
+ */
32
68
  arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
69
+ /**
70
+ * Whether the regexps passed are equal in value.
71
+ */
33
72
  areRegExpsEqual: TypeEqualityComparator<any, Meta>;
73
+ /**
74
+ * Whether the sets passed are equal in value. In strict mode, this includes
75
+ * additional properties added to the set.
76
+ */
34
77
  areSetsEqual: TypeEqualityComparator<any, Meta>;
78
+ /**
79
+ * Whether the typed arrays passed are equal in value. In strict mode, this includes
80
+ * additional properties added to the typed array.
81
+ */
35
82
  areTypedArraysEqual: TypeEqualityComparator<any, Meta>;
36
83
  }
37
84
 
@@ -73,6 +120,17 @@ export type InternalEqualityComparator<Meta> = (
73
120
  // eslint-disable-next-line @typescript-eslint/ban-types
74
121
  export type PrimitiveWrapper = Boolean | Number | String;
75
122
 
123
+ /**
124
+ * Type which encompasses possible instances of TypedArray
125
+ * classes.
126
+ *
127
+ * **NOTE**: This does not include `BigInt64Array` and
128
+ * `BitUint64Array` because those are part of ES2020 and
129
+ * not supported by certain TS configurations. If using
130
+ * either in `areTypedArraysEqual`, you can cast the
131
+ * instance as `TypedArray` and it will work as expected,
132
+ * because runtime checks will still work for those classes.
133
+ */
76
134
  export type TypedArray =
77
135
  | Float32Array
78
136
  | Float64Array
@@ -91,11 +149,37 @@ export type TypeEqualityComparator<Type, Meta = undefined> = (
91
149
  ) => boolean;
92
150
 
93
151
  export interface CustomEqualCreatorOptions<Meta> {
152
+ /**
153
+ * Whether circular references should be supported. It causes the
154
+ * comparison to be slower, but for objects that have circular references
155
+ * it is required to avoid stack overflows.
156
+ */
94
157
  circular?: boolean;
158
+ /**
159
+ * Create a custom configuration of type-specific equality comparators.
160
+ * This receives the default configuration, which allows either replacement
161
+ * or supersetting of the default methods.
162
+ */
95
163
  createCustomConfig?: CreateCustomComparatorConfig<Meta>;
164
+ /**
165
+ * Create a custom internal comparator, which is used as an override to the
166
+ * default entry point for nested value equality comparisons. This is often
167
+ * used for doing custom logic for specific types (such as handling a specific
168
+ * class instance differently than other objects) or to incorporate `meta` in
169
+ * the comparison. See the recipes for examples.
170
+ */
96
171
  createInternalComparator?: (
97
172
  compare: EqualityComparator<Meta>,
98
173
  ) => InternalEqualityComparator<Meta>;
174
+ /**
175
+ * Create a custom `state` object passed between the methods. This allows for
176
+ * custom `cache` and/or `meta` values to be used.
177
+ */
99
178
  createState?: CreateState<Meta>;
179
+ /**
180
+ * Whether the equality comparison is strict, meaning it matches
181
+ * all properties (including symbols and non-enumerable properties)
182
+ * with equal shape of descriptors.
183
+ */
100
184
  strict?: boolean;
101
185
  }