fast-equals 4.0.3 → 5.0.0-beta.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/.babelrc +34 -0
- package/.prettierrc +4 -0
- package/CHANGELOG.md +39 -0
- package/README.md +146 -39
- package/build/rollup/config.base.js +49 -0
- package/build/rollup/config.cjs.js +10 -0
- package/build/rollup/config.esm.js +10 -0
- package/build/rollup/config.min.js +13 -0
- package/build/rollup/config.umd.js +10 -0
- package/build/tsconfig/base.json +32 -0
- package/build/tsconfig/cjs.json +8 -0
- package/build/tsconfig/declarations.json +9 -0
- package/build/tsconfig/esm.json +8 -0
- package/build/tsconfig/min.json +8 -0
- package/build/tsconfig/umd.json +8 -0
- package/build/webpack.config.js +57 -0
- package/dist/cjs/index.cjs +510 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/types/comparator.d.ts +2 -0
- package/dist/cjs/types/equals.d.ts +46 -0
- package/dist/cjs/types/index.d.ts +56 -0
- package/dist/cjs/types/internalTypes.d.ts +36 -0
- package/dist/cjs/types/utils.d.ts +19 -0
- package/dist/esm/index.mjs +499 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/types/comparator.d.ts +2 -0
- package/dist/esm/types/equals.d.ts +46 -0
- package/dist/esm/types/index.d.ts +56 -0
- package/dist/esm/types/internalTypes.d.ts +36 -0
- package/dist/esm/types/utils.d.ts +19 -0
- package/dist/min/index.js +1 -0
- package/dist/min/types/comparator.d.ts +2 -0
- package/dist/min/types/equals.d.ts +46 -0
- package/dist/min/types/index.d.ts +56 -0
- package/dist/min/types/internalTypes.d.ts +36 -0
- package/dist/min/types/utils.d.ts +19 -0
- package/dist/umd/index.js +516 -0
- package/dist/umd/index.js.map +1 -0
- package/dist/umd/types/comparator.d.ts +2 -0
- package/dist/umd/types/equals.d.ts +46 -0
- package/dist/umd/types/index.d.ts +56 -0
- package/dist/umd/types/internalTypes.d.ts +36 -0
- package/dist/umd/types/utils.d.ts +19 -0
- package/index.d.ts +62 -55
- package/package.json +59 -38
- package/recipes/explicit-property-check.md +4 -6
- package/recipes/legacy-circular-equal-support.md +28 -20
- package/recipes/legacy-regexp-support.md +15 -16
- package/recipes/non-standard-properties.md +35 -23
- package/recipes/using-meta-in-comparison.md +10 -13
- package/src/comparator.ts +43 -40
- package/src/equals.ts +263 -0
- package/src/index.ts +183 -79
- package/src/internalTypes.ts +74 -0
- package/src/utils.ts +42 -49
- package/dist/fast-equals.cjs.js +0 -432
- package/dist/fast-equals.cjs.js.map +0 -1
- package/dist/fast-equals.esm.js +0 -422
- package/dist/fast-equals.esm.js.map +0 -1
- package/dist/fast-equals.js +0 -438
- package/dist/fast-equals.js.map +0 -1
- package/dist/fast-equals.min.js +0 -1
- package/dist/fast-equals.mjs +0 -422
- package/dist/fast-equals.mjs.map +0 -1
- package/recipes/strict-property-descriptor-check.md +0 -42
- package/src/arrays.ts +0 -36
- package/src/dates.ts +0 -12
- package/src/maps.ts +0 -66
- package/src/objects.ts +0 -62
- package/src/regexps.ts +0 -11
- package/src/sets.ts +0 -61
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { CreateCustomComparatorConfig, CreateState, EqualityComparator } from './internalTypes';
|
|
2
|
+
import { createInternalComparator, sameValueZeroEqual } from './utils';
|
|
3
|
+
export { sameValueZeroEqual };
|
|
4
|
+
interface DefaultEqualCreatorOptions<Meta> {
|
|
5
|
+
comparator?: EqualityComparator<Meta>;
|
|
6
|
+
circular?: boolean;
|
|
7
|
+
strict?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface CustomEqualCreatorOptions<Meta> extends DefaultEqualCreatorOptions<Meta> {
|
|
10
|
+
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
|
|
11
|
+
createInternalComparator?: typeof createInternalComparator;
|
|
12
|
+
createState?: CreateState<Meta>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Whether the items passed are deeply-equal in value.
|
|
16
|
+
*/
|
|
17
|
+
export declare const deepEqual: <A, B>(a: A, b: B) => boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Whether the items passed are deeply-equal in value based on strict comparison.
|
|
20
|
+
*/
|
|
21
|
+
export declare const strictDeepEqual: <A, B>(a: A, b: B) => boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the items passed are deeply-equal in value, including circular references.
|
|
24
|
+
*/
|
|
25
|
+
export declare const circularDeepEqual: <A, B>(a: A, b: B) => boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Whether the items passed are deeply-equal in value, including circular references,
|
|
28
|
+
* based on strict comparison.
|
|
29
|
+
*/
|
|
30
|
+
export declare const strictCircularDeepEqual: <A, B>(a: A, b: B) => boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether the items passed are shallowly-equal in value.
|
|
33
|
+
*/
|
|
34
|
+
export declare const shallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Whether the items passed are shallowly-equal in value based on strict comparison
|
|
37
|
+
*/
|
|
38
|
+
export declare const strictShallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Whether the items passed are shallowly-equal in value, including circular references.
|
|
41
|
+
*/
|
|
42
|
+
export declare const circularShallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the items passed are shallowly-equal in value, including circular references,
|
|
45
|
+
* based on strict comparison.
|
|
46
|
+
*/
|
|
47
|
+
export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Create a custom equality comparison method.
|
|
50
|
+
*
|
|
51
|
+
* This can be done to create very targeted comparisons in extreme hot-path scenarios
|
|
52
|
+
* where the standard methods are not performant enough, but can also be used to provide
|
|
53
|
+
* support for legacy environments that do not support expected features like
|
|
54
|
+
* `RegExp.prototype.flags` out of the box.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createCustomEqual<Meta>(options?: CustomEqualCreatorOptions<Meta>): <A, B>(a: A, b: B, metaOverride?: Meta) => boolean;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface BaseCircular extends Pick<WeakMap<any, any>, 'delete' | 'get'> {
|
|
2
|
+
set(key: object, value: any): any;
|
|
3
|
+
}
|
|
4
|
+
export type State<Meta> = CircularState<Meta> | DefaultState<Meta>;
|
|
5
|
+
export interface CircularState<Meta> {
|
|
6
|
+
readonly cache: BaseCircular;
|
|
7
|
+
readonly equals: InternalEqualityComparator<Meta>;
|
|
8
|
+
meta: Meta;
|
|
9
|
+
readonly strict: boolean;
|
|
10
|
+
}
|
|
11
|
+
export interface DefaultState<Meta> {
|
|
12
|
+
readonly cache: undefined;
|
|
13
|
+
readonly equals: InternalEqualityComparator<Meta>;
|
|
14
|
+
meta: Meta;
|
|
15
|
+
readonly strict: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface Dictionary<Value = any> {
|
|
18
|
+
[key: string | symbol]: Value;
|
|
19
|
+
$$typeof?: any;
|
|
20
|
+
}
|
|
21
|
+
export interface ComparatorConfig<Meta> {
|
|
22
|
+
areArraysEqual: TypeEqualityComparator<any, Meta>;
|
|
23
|
+
areDatesEqual: TypeEqualityComparator<any, Meta>;
|
|
24
|
+
areMapsEqual: TypeEqualityComparator<any, Meta>;
|
|
25
|
+
areObjectsEqual: TypeEqualityComparator<any, Meta>;
|
|
26
|
+
arePrimitiveWrappersEqual: TypeEqualityComparator<any, Meta>;
|
|
27
|
+
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
|
|
28
|
+
areSetsEqual: TypeEqualityComparator<any, Meta>;
|
|
29
|
+
}
|
|
30
|
+
export type CreateCustomComparatorConfig<Meta> = (config: ComparatorConfig<Meta>) => Partial<ComparatorConfig<Meta>>;
|
|
31
|
+
export type CreateState<Meta> = (comparator: EqualityComparator<Meta>) => Partial<State<Meta>>;
|
|
32
|
+
export type EqualityComparator<Meta> = <A, B>(a: A, b: B, state: State<Meta>) => boolean;
|
|
33
|
+
export type AnyEqualityComparator<Meta> = (a: any, b: any, state: State<Meta>) => boolean;
|
|
34
|
+
export type EqualityComparatorCreator<Meta> = (fn: EqualityComparator<Meta>) => InternalEqualityComparator<Meta>;
|
|
35
|
+
export type InternalEqualityComparator<Meta> = (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State<Meta>) => boolean;
|
|
36
|
+
export type TypeEqualityComparator<Type, Meta = undefined> = (a: Type, b: Type, state: State<Meta>) => boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { AnyEqualityComparator, Dictionary, EqualityComparator, InternalEqualityComparator, State, TypeEqualityComparator } from './internalTypes';
|
|
2
|
+
export declare function combineComparators<Meta>(comparatorA: AnyEqualityComparator<Meta>, comparatorB: AnyEqualityComparator<Meta>): <A, B>(a: A, b: B, state: State<Meta>) => boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Default equality comparator pass-through, used as the standard `isEqual` creator for
|
|
5
|
+
* use inside the built comparator.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createInternalComparator<Meta>(compare: EqualityComparator<Meta>): InternalEqualityComparator<Meta>;
|
|
8
|
+
/**
|
|
9
|
+
* Wrap the provided `areItemsEqual` method to manage the circular state, allowing
|
|
10
|
+
* for circular references to be safely included in the comparison without creating
|
|
11
|
+
* stack overflows.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createIsCircular<AreItemsEqual extends TypeEqualityComparator<any, any>>(areItemsEqual: AreItemsEqual): AreItemsEqual;
|
|
14
|
+
export declare function getStrictProperties(object: Dictionary): Array<string | symbol>;
|
|
15
|
+
export declare const hasOwn: (o: object, v: PropertyKey) => boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the values passed are strictly equal or both NaN.
|
|
18
|
+
*/
|
|
19
|
+
export declare function sameValueZeroEqual(a: any, b: any): boolean;
|
package/index.d.ts
CHANGED
|
@@ -1,58 +1,65 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import type {
|
|
2
|
+
CreateCustomComparatorConfig,
|
|
3
|
+
CreateState,
|
|
4
|
+
EqualityComparator,
|
|
5
|
+
} from './src/internalTypes';
|
|
6
|
+
import { createInternalComparator, sameValueZeroEqual } from './src/utils';
|
|
7
|
+
export { sameValueZeroEqual };
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
interface DefaultEqualCreatorOptions<Meta> {
|
|
10
|
+
comparator?: EqualityComparator<Meta>;
|
|
11
|
+
circular?: boolean;
|
|
12
|
+
strict?: boolean;
|
|
13
|
+
}
|
|
14
|
+
interface CustomEqualCreatorOptions<Meta>
|
|
15
|
+
extends DefaultEqualCreatorOptions<Meta> {
|
|
16
|
+
createCustomConfig?: CreateCustomComparatorConfig<Meta>;
|
|
17
|
+
createInternalComparator?: typeof createInternalComparator;
|
|
18
|
+
createState?: CreateState<Meta>;
|
|
14
19
|
}
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
) =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
export
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
export
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Whether the items passed are deeply-equal in value.
|
|
23
|
+
*/
|
|
24
|
+
export declare const deepEqual: <A, B>(a: A, b: B) => boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Whether the items passed are deeply-equal in value based on strict comparison.
|
|
27
|
+
*/
|
|
28
|
+
export declare const strictDeepEqual: <A, B>(a: A, b: B) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Whether the items passed are deeply-equal in value, including circular references.
|
|
31
|
+
*/
|
|
32
|
+
export declare const circularDeepEqual: <A, B>(a: A, b: B) => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the items passed are deeply-equal in value, including circular references,
|
|
35
|
+
* based on strict comparison.
|
|
36
|
+
*/
|
|
37
|
+
export declare const strictCircularDeepEqual: <A, B>(a: A, b: B) => boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Whether the items passed are shallowly-equal in value.
|
|
40
|
+
*/
|
|
41
|
+
export declare const shallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the items passed are shallowly-equal in value based on strict comparison
|
|
44
|
+
*/
|
|
45
|
+
export declare const strictShallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the items passed are shallowly-equal in value, including circular references.
|
|
48
|
+
*/
|
|
49
|
+
export declare const circularShallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Whether the items passed are shallowly-equal in value, including circular references,
|
|
52
|
+
* based on strict comparison.
|
|
53
|
+
*/
|
|
54
|
+
export declare const strictCircularShallowEqual: <A, B>(a: A, b: B) => boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Create a custom equality comparison method.
|
|
57
|
+
*
|
|
58
|
+
* This can be done to create very targeted comparisons in extreme hot-path scenarios
|
|
59
|
+
* where the standard methods are not performant enough, but can also be used to provide
|
|
60
|
+
* support for legacy environments that do not support expected features like
|
|
61
|
+
* `RegExp.prototype.flags` out of the box.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createCustomEqual<Meta>(
|
|
64
|
+
options?: CustomEqualCreatorOptions<Meta>,
|
|
65
|
+
): <A, B>(a: A, b: B, metaOverride?: Meta) => boolean;
|
package/package.json
CHANGED
|
@@ -1,53 +1,69 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "tony_quetano@planttheidea.com",
|
|
3
|
-
"browser": "dist/
|
|
3
|
+
"browser": "dist/umd/index.js",
|
|
4
4
|
"bugs": {
|
|
5
5
|
"url": "https://github.com/planttheidea/fast-equals/issues"
|
|
6
6
|
},
|
|
7
7
|
"description": "A blazing fast equality comparison, either shallow or deep",
|
|
8
8
|
"devDependencies": {
|
|
9
|
-
"@rollup/plugin-
|
|
10
|
-
"@
|
|
9
|
+
"@rollup/plugin-commonjs": "^24.0.0",
|
|
10
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
11
|
+
"@rollup/plugin-replace": "^5.0.2",
|
|
12
|
+
"@rollup/plugin-terser": "^0.4.0",
|
|
13
|
+
"@rollup/plugin-typescript": "^11.0.0",
|
|
14
|
+
"@types/jest": "^29.2.5",
|
|
11
15
|
"@types/lodash": "^4.14.184",
|
|
12
|
-
"@types/node": "^18.
|
|
13
|
-
"@types/ramda": "^0.28.
|
|
14
|
-
"@types/react": "^18.0.
|
|
15
|
-
"@
|
|
16
|
-
"@typescript-eslint/
|
|
17
|
-
"
|
|
18
|
-
"cli-table3": "^0.6.1",
|
|
16
|
+
"@types/node": "^18.14.0",
|
|
17
|
+
"@types/ramda": "^0.28.23",
|
|
18
|
+
"@types/react": "^18.0.28",
|
|
19
|
+
"@types/react-dom": "^18.0.11",
|
|
20
|
+
"@typescript-eslint/eslint-plugin": "^5.52.0",
|
|
21
|
+
"@typescript-eslint/parser": "^5.52.0",
|
|
19
22
|
"decircularize": "^1.0.0",
|
|
20
23
|
"deep-eql": "^4.1.0",
|
|
21
24
|
"deep-equal": "^2.0.5",
|
|
22
|
-
"eslint": "^8.
|
|
23
|
-
"eslint-
|
|
24
|
-
"eslint-plugin
|
|
25
|
-
"eslint-plugin-jsx-a11y": "^6.6.1",
|
|
26
|
-
"eslint-plugin-react": "^7.31.0",
|
|
27
|
-
"eslint-webpack-plugin": "^3.2.0",
|
|
25
|
+
"eslint": "^8.34.0",
|
|
26
|
+
"eslint-friendly-formatter": "^4.0.1",
|
|
27
|
+
"eslint-webpack-plugin": "^4.0.0",
|
|
28
28
|
"fast-deep-equal": "^3.1.3",
|
|
29
|
-
"fs-extra": "^10.0.0",
|
|
30
29
|
"html-webpack-plugin": "^5.5.0",
|
|
31
30
|
"in-publish": "^2.0.0",
|
|
32
|
-
"jest": "^
|
|
31
|
+
"jest": "^29.4.3",
|
|
32
|
+
"jest-environment-jsdom": "^29.4.3",
|
|
33
|
+
"jest-expect-message": "^1.1.3",
|
|
33
34
|
"lodash": "^4.17.21",
|
|
34
35
|
"nano-equal": "^2.0.2",
|
|
35
|
-
"prettier": "^2.
|
|
36
|
+
"prettier": "^2.8.4",
|
|
36
37
|
"react": "^18.2.0",
|
|
37
38
|
"react-dom": "^18.2.0",
|
|
38
39
|
"react-fast-compare": "^3.2.0",
|
|
39
|
-
"release-it": "^15.
|
|
40
|
-
"rollup": "^
|
|
41
|
-
"rollup-plugin-terser": "^7.0.2",
|
|
42
|
-
"rollup-plugin-typescript2": "^0.33.0",
|
|
40
|
+
"release-it": "^15.6.0",
|
|
41
|
+
"rollup": "^3.16.0",
|
|
43
42
|
"shallow-equal-fuzzy": "^0.0.2",
|
|
44
|
-
"
|
|
45
|
-
"ts-
|
|
46
|
-
"
|
|
43
|
+
"tinybench": "^2.3.1",
|
|
44
|
+
"ts-jest": "^29.0.3",
|
|
45
|
+
"ts-loader": "^9.4.2",
|
|
46
|
+
"typescript": "^4.9.5",
|
|
47
47
|
"underscore": "^1.13.4",
|
|
48
|
-
"webpack": "^5.
|
|
49
|
-
"webpack-cli": "^
|
|
50
|
-
"webpack-dev-server": "^4.
|
|
48
|
+
"webpack": "^5.75.0",
|
|
49
|
+
"webpack-cli": "^5.0.1",
|
|
50
|
+
"webpack-dev-server": "^4.11.1"
|
|
51
|
+
},
|
|
52
|
+
"exports": {
|
|
53
|
+
".": {
|
|
54
|
+
"import": {
|
|
55
|
+
"types": "./dist/esm/types/index.d.ts",
|
|
56
|
+
"default": "./dist/esm/index.mjs"
|
|
57
|
+
},
|
|
58
|
+
"require": {
|
|
59
|
+
"types": "./dist/cjs/types/index.d.ts",
|
|
60
|
+
"default": "./dist/cjs/index.cjs"
|
|
61
|
+
},
|
|
62
|
+
"default": {
|
|
63
|
+
"types": "./dist/umd/types/index.d.ts",
|
|
64
|
+
"default": "./dist/umd/index.js"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
51
67
|
},
|
|
52
68
|
"homepage": "https://github.com/planttheidea/fast-equals#readme",
|
|
53
69
|
"keywords": [
|
|
@@ -58,32 +74,37 @@
|
|
|
58
74
|
"equivalent"
|
|
59
75
|
],
|
|
60
76
|
"license": "MIT",
|
|
61
|
-
"main": "dist/
|
|
62
|
-
"module": "dist/
|
|
77
|
+
"main": "dist/cjs/index.cjs",
|
|
78
|
+
"module": "dist/esm/index.mjs",
|
|
63
79
|
"name": "fast-equals",
|
|
64
80
|
"repository": {
|
|
65
81
|
"type": "git",
|
|
66
82
|
"url": "git+https://github.com/planttheidea/fast-equals.git"
|
|
67
83
|
},
|
|
68
84
|
"scripts": {
|
|
69
|
-
"benchmark": "npm run
|
|
70
|
-
"build": "
|
|
71
|
-
"
|
|
85
|
+
"benchmark": "npm run build:esm && node benchmark/index.js",
|
|
86
|
+
"build": "npm run build:esm && npm run build:cjs && npm run build:umd && npm run build:min",
|
|
87
|
+
"build:cjs": "rimraf dist/cjs && NODE_ENV=production rollup -c build/rollup/config.cjs.js && tsc -p ./build/tsconfig/cjs.json",
|
|
88
|
+
"build:esm": "rimraf dist/esm && NODE_ENV=production rollup -c build/rollup/config.esm.js && tsc -p ./build/tsconfig/esm.json",
|
|
89
|
+
"build:min": "rimraf dist/min && NODE_ENV=production rollup -c build/rollup/config.min.js && tsc -p ./build/tsconfig/min.json",
|
|
90
|
+
"build:umd": "rimraf dist/umd && NODE_ENV=production rollup -c build/rollup/config.umd.js && tsc -p ./build/tsconfig/umd.json",
|
|
91
|
+
"dev": "NODE_ENV=development webpack serve --progress --config=build/webpack.config.js",
|
|
72
92
|
"dist": "rimraf dist && npm run build",
|
|
73
93
|
"format": "prettier **/*.ts --write",
|
|
74
94
|
"lint": "eslint src/*.ts",
|
|
75
95
|
"lint:fix": "npm run lint -- --fix",
|
|
76
96
|
"start": "npm run dev",
|
|
77
97
|
"prepublish": "if in-publish; then npm run prepublish:compile; fi",
|
|
78
|
-
"prepublish:compile": "npm run typecheck && npm run lint && npm run test && npm run dist",
|
|
79
98
|
"release": "release-it",
|
|
80
99
|
"release:beta": "release-it --config=.release-it.beta.json",
|
|
100
|
+
"release:scripts": "npm run typecheck && npm run lint && npm run test && npm run dist",
|
|
81
101
|
"test": "NODE_PATH=. jest",
|
|
82
|
-
"test:coverage": "npm test -- --coverage",
|
|
102
|
+
"test:coverage": "rimraf coverage && npm test -- --coverage",
|
|
83
103
|
"test:watch": "npm test -- --watch",
|
|
84
104
|
"typecheck": "tsc --noEmit"
|
|
85
105
|
},
|
|
86
106
|
"sideEffects": false,
|
|
87
|
-
"
|
|
88
|
-
"
|
|
107
|
+
"type": "module",
|
|
108
|
+
"types": "./index.d.ts",
|
|
109
|
+
"version": "5.0.0-beta.1"
|
|
89
110
|
}
|
|
@@ -18,11 +18,9 @@ interface SpecialObject {
|
|
|
18
18
|
const areObjectsEqual: TypeEqualityComparator<SpecialObject, undefined> = (
|
|
19
19
|
a,
|
|
20
20
|
b,
|
|
21
|
-
) =>
|
|
22
|
-
return a.foo === b.foo && a.bar.baz === b.bar.baz;
|
|
23
|
-
};
|
|
21
|
+
) => a.foo === b.foo && a.bar.baz === b.bar.baz;
|
|
24
22
|
|
|
25
|
-
const isSpecialObjectEqual = createCustomEqual(
|
|
26
|
-
areObjectsEqual,
|
|
27
|
-
})
|
|
23
|
+
const isSpecialObjectEqual = createCustomEqual({
|
|
24
|
+
createCustomConfig: () => ({ areObjectsEqual }),
|
|
25
|
+
});
|
|
28
26
|
```
|
|
@@ -3,14 +3,9 @@
|
|
|
3
3
|
Starting in `4.x.x`, `WeakMap` is expected to be available in the environment. All modern browsers support this global object, however there may be situations where a legacy environmental support is required (example: IE11). If you need to support such an environment, creating a custom comparator that uses a custom cache implementation with the same contract is a simple solution.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
|
-
import { createCustomEqual, sameValueZeroEqual } from '
|
|
6
|
+
import { createCustomEqual, sameValueZeroEqual } from 'fast-equals';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
customMethod(): void;
|
|
10
|
-
customValue: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function getCache(): Cache {
|
|
8
|
+
function getCache(): BaseCircular {
|
|
14
9
|
const entries: Array<[object, any]> = [];
|
|
15
10
|
|
|
16
11
|
return {
|
|
@@ -45,22 +40,35 @@ function getCache(): Cache {
|
|
|
45
40
|
|
|
46
41
|
return this;
|
|
47
42
|
},
|
|
48
|
-
|
|
49
|
-
customMethod() {
|
|
50
|
-
console.log('hello!');
|
|
51
|
-
},
|
|
52
|
-
customValue: 'goodbye',
|
|
53
43
|
};
|
|
54
44
|
}
|
|
55
45
|
|
|
56
|
-
|
|
46
|
+
interface Meta {
|
|
47
|
+
customMethod(): void;
|
|
48
|
+
customValue: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const meta = {
|
|
52
|
+
customMethod() {
|
|
53
|
+
console.log('hello!');
|
|
54
|
+
},
|
|
55
|
+
customValue: 'goodbye',
|
|
56
|
+
};
|
|
57
57
|
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
const circularDeepEqual = createCustomEqual<Cache>({
|
|
59
|
+
circular: true,
|
|
60
|
+
createState: () => ({
|
|
61
|
+
cache: getCache(),
|
|
62
|
+
meta,
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
61
65
|
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
+
const circularShallowEqual = createCustomEqual<Cache>({
|
|
67
|
+
circular: true,
|
|
68
|
+
comparator: sameValueZeroEqual,
|
|
69
|
+
createState: () => ({
|
|
70
|
+
cache: getCache(),
|
|
71
|
+
meta,
|
|
72
|
+
}),
|
|
73
|
+
});
|
|
66
74
|
```
|
|
@@ -6,21 +6,20 @@ Starting in `4.x.x`, `RegExp.prototype.flags` is expected to be available in the
|
|
|
6
6
|
import { createCustomEqual, sameValueZeroEqual } from 'deep-Equals';
|
|
7
7
|
import type { TypeEqualityComparator } from 'fast-equals';
|
|
8
8
|
|
|
9
|
-
const areRegExpsEqual: TypeEqualityComparator<RegExp, undefined> = (a, b) =>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
a.lastIndex === b.lastIndex
|
|
18
|
-
);
|
|
19
|
-
};
|
|
9
|
+
const areRegExpsEqual: TypeEqualityComparator<RegExp, undefined> = (a, b) =>
|
|
10
|
+
a.source === b.source &&
|
|
11
|
+
a.global === b.global &&
|
|
12
|
+
a.ignoreCase === b.ignoreCase &&
|
|
13
|
+
a.multiline === b.multiline &&
|
|
14
|
+
a.unicode === b.unicode &&
|
|
15
|
+
a.sticky === b.sticky &&
|
|
16
|
+
a.lastIndex === b.lastIndex;
|
|
20
17
|
|
|
21
|
-
const deepEqual = createCustomEqual(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
18
|
+
const deepEqual = createCustomEqual({
|
|
19
|
+
createCustomConfig: () => ({ areRegExpsEqual }),
|
|
20
|
+
});
|
|
21
|
+
const shallowEqual = createCustomEqual({
|
|
22
|
+
comparator: sameValueZero,
|
|
23
|
+
createCustomConfig: () => ({ areRegExpsEqual }),
|
|
24
|
+
});
|
|
26
25
|
```
|
|
@@ -1,34 +1,46 @@
|
|
|
1
1
|
# Non-standard properties
|
|
2
2
|
|
|
3
|
-
Sometimes, objects require a comparison that extend beyond its own keys
|
|
4
|
-
|
|
5
|
-
Using a custom object comparator with `createCustomEqual` allows these kinds of comparisons.
|
|
3
|
+
Sometimes, objects require a comparison that extend beyond its own keys, or even its own properties or symbols. Using a custom object comparator with `createCustomEqual` allows these kinds of comparisons.
|
|
6
4
|
|
|
7
5
|
```ts
|
|
8
6
|
import { createCustomEqual } from 'fast-equals';
|
|
9
7
|
import type { TypeEqualityComparator } from 'fast-equals';
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
if (propertiesA.length !== propertiesB.length) {
|
|
25
|
-
return false;
|
|
9
|
+
class HiddenProperty {
|
|
10
|
+
visible: boolean;
|
|
11
|
+
#hidden: string;
|
|
12
|
+
|
|
13
|
+
constructor(value: string) {
|
|
14
|
+
this.visible = true;
|
|
15
|
+
this.#hidden = value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get hidden() {
|
|
19
|
+
return this.#hidden;
|
|
26
20
|
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createAreObjectsEqual(
|
|
24
|
+
areObjectsEqual: TypeEqualityComparator<Record<any, any>, undefined>,
|
|
25
|
+
): TypeEqualityComparator<Record<any, any>, undefined> {
|
|
26
|
+
return function (a, b, state) {
|
|
27
|
+
if (!areObjectsEqual(a, b, state)) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const aInstance = a instanceof HiddenProperty;
|
|
32
|
+
const bInstance = b instanceof HiddenProperty;
|
|
33
|
+
|
|
34
|
+
if (aInstance || bInstance) {
|
|
35
|
+
return aInstance && bInstance && a.hidden === b.hidden;
|
|
36
|
+
}
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
38
|
+
return true;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
32
41
|
|
|
33
|
-
const deepEqual = createCustomEqual(
|
|
42
|
+
const deepEqual = createCustomEqual({
|
|
43
|
+
createCustomConfig: ({ areObjectsEqual }) =>
|
|
44
|
+
createAreObjectsEqual(areObjectsEqual),
|
|
45
|
+
});
|
|
34
46
|
```
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
# Using `meta` in comparison
|
|
2
2
|
|
|
3
|
-
Sometimes a "pure" equality between two objects is insufficient, because the comparison relies on some external state. While these kinds of scenarios should generally be avoided, it is possible to handle them with a custom comparator that checks `meta` values.
|
|
3
|
+
Sometimes a "pure" equality between two objects is insufficient, because the comparison relies on some external state. While these kinds of scenarios should generally be avoided, it is possible to handle them with a custom internal comparator that checks `meta` values.
|
|
4
4
|
|
|
5
5
|
```ts
|
|
6
6
|
import { createCustomEqual } from 'fast-equals';
|
|
7
|
-
import type {
|
|
8
|
-
EqualityComparator,
|
|
9
|
-
InternalEqualityComparator,
|
|
10
|
-
} from 'fast-equals';
|
|
11
7
|
|
|
12
|
-
interface
|
|
13
|
-
|
|
8
|
+
interface Meta {
|
|
9
|
+
value: string;
|
|
14
10
|
}
|
|
15
11
|
|
|
16
|
-
const
|
|
12
|
+
const meta: Meta = { value: 'baz' };
|
|
17
13
|
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
const deepEqual = createCustomEqual<Meta>({
|
|
15
|
+
createInternalComparator:
|
|
16
|
+
(compare) => (a, b, _keyA, _keyB, _parentA, _parentB, state) =>
|
|
17
|
+
compare(a, b, state) || a === state.meta.value || b === state.meta.value,
|
|
18
|
+
createState: () => ({ meta }),
|
|
19
|
+
});
|
|
23
20
|
```
|