fast-equals 5.3.1 → 5.3.3-beta.0
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 +9 -0
- package/README.md +1 -1
- package/dist/cjs/index.cjs +9 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/types/{comparator.d.ts → comparator.d.cts} +1 -1
- package/dist/{esm/types/equals.d.ts → cjs/types/equals.d.cts} +2 -2
- package/dist/cjs/types/{index.d.ts → index.d.cts} +3 -3
- package/dist/{esm/types/utils.d.ts → cjs/types/utils.d.cts} +1 -1
- package/dist/esm/index.mjs +9 -3
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/types/{comparator.d.ts → comparator.d.mts} +1 -1
- package/dist/{cjs/types/equals.d.ts → esm/types/equals.d.mts} +2 -2
- package/dist/esm/types/{index.d.ts → index.d.mts} +3 -3
- package/dist/{cjs/types/utils.d.ts → esm/types/utils.d.mts} +1 -1
- package/dist/min/index.js +1 -1
- package/dist/min/types/comparator.d.ts +1 -1
- package/dist/min/types/equals.d.ts +1 -1
- package/dist/min/types/index.d.ts +2 -2
- package/dist/min/types/utils.d.ts +1 -1
- package/dist/umd/index.js +9 -3
- package/dist/umd/index.js.map +1 -1
- package/dist/umd/types/comparator.d.ts +1 -1
- package/dist/umd/types/equals.d.ts +1 -1
- package/dist/umd/types/index.d.ts +2 -2
- package/dist/umd/types/utils.d.ts +1 -1
- package/index.d.ts +1 -1
- package/package.json +51 -41
- package/src/comparator.ts +7 -7
- package/src/equals.ts +8 -4
- package/src/index.ts +4 -4
- package/src/internalTypes.ts +1 -1
- package/src/utils.ts +2 -1
- package/.babelrc +0 -34
- package/.prettierrc +0 -8
- package/.release-it.beta.json +0 -18
- package/.release-it.json +0 -14
- package/.yarnrc.yml +0 -5
- package/BUILD.md +0 -37
- package/config/rollup/config.base.js +0 -49
- package/config/rollup/config.cjs.js +0 -10
- package/config/rollup/config.esm.js +0 -10
- package/config/rollup/config.min.js +0 -13
- package/config/rollup/config.umd.js +0 -10
- package/config/tsconfig/base.json +0 -32
- package/config/tsconfig/cjs.json +0 -8
- package/config/tsconfig/declarations.json +0 -9
- package/config/tsconfig/esm.json +0 -8
- package/config/tsconfig/min.json +0 -8
- package/config/tsconfig/umd.json +0 -8
- package/config/webpack.config.js +0 -57
- package/recipes/explicit-property-check.md +0 -26
- package/recipes/legacy-circular-equal-support.md +0 -75
- package/recipes/legacy-regexp-support.md +0 -24
- package/recipes/non-standard-properties.md +0 -48
- package/recipes/special-objects.md +0 -25
- package/recipes/using-meta-in-comparison.md +0 -20
- package/scripts/apply-type-file-extensions.mjs +0 -33
- package/scripts/fallback-types.mjs +0 -64
- /package/dist/cjs/types/{internalTypes.d.ts → internalTypes.d.cts} +0 -0
- /package/dist/esm/types/{internalTypes.d.ts → internalTypes.d.mts} +0 -0
package/src/equals.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { getStrictProperties, hasOwn, sameValueZeroEqual } from './utils';
|
|
1
|
+
import { getStrictProperties, hasOwn, sameValueZeroEqual } from './utils.ts';
|
|
2
2
|
import type {
|
|
3
3
|
Dictionary,
|
|
4
4
|
PrimitiveWrapper,
|
|
5
5
|
State,
|
|
6
6
|
TypedArray,
|
|
7
|
-
} from './internalTypes';
|
|
7
|
+
} from './internalTypes.ts';
|
|
8
8
|
|
|
9
9
|
const PREACT_VNODE = '__v';
|
|
10
10
|
const PREACT_OWNER = '__o';
|
|
@@ -78,13 +78,14 @@ export function areMapsEqual(
|
|
|
78
78
|
return true;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
-
const matchedIndices
|
|
81
|
+
const matchedIndices = new Array<true | undefined>(size);
|
|
82
82
|
const aIterable = a.entries();
|
|
83
83
|
|
|
84
84
|
let aResult: IteratorResult<[any, any]>;
|
|
85
85
|
let bResult: IteratorResult<[any, any]>;
|
|
86
86
|
let index = 0;
|
|
87
87
|
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
88
89
|
while ((aResult = aIterable.next())) {
|
|
89
90
|
if (aResult.done) {
|
|
90
91
|
break;
|
|
@@ -95,6 +96,7 @@ export function areMapsEqual(
|
|
|
95
96
|
let hasMatch = false;
|
|
96
97
|
let matchIndex = 0;
|
|
97
98
|
|
|
99
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
98
100
|
while ((bResult = bIterable.next())) {
|
|
99
101
|
if (bResult.done) {
|
|
100
102
|
break;
|
|
@@ -247,12 +249,13 @@ export function areSetsEqual(
|
|
|
247
249
|
return true;
|
|
248
250
|
}
|
|
249
251
|
|
|
250
|
-
const matchedIndices
|
|
252
|
+
const matchedIndices = new Array<true | undefined>(size);
|
|
251
253
|
const aIterable = a.values();
|
|
252
254
|
|
|
253
255
|
let aResult: IteratorResult<any>;
|
|
254
256
|
let bResult: IteratorResult<any>;
|
|
255
257
|
|
|
258
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
256
259
|
while ((aResult = aIterable.next())) {
|
|
257
260
|
if (aResult.done) {
|
|
258
261
|
break;
|
|
@@ -263,6 +266,7 @@ export function areSetsEqual(
|
|
|
263
266
|
let hasMatch = false;
|
|
264
267
|
let matchIndex = 0;
|
|
265
268
|
|
|
269
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
266
270
|
while ((bResult = bIterable.next())) {
|
|
267
271
|
if (bResult.done) {
|
|
268
272
|
break;
|
package/src/index.ts
CHANGED
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
createEqualityComparator,
|
|
4
4
|
createInternalEqualityComparator,
|
|
5
5
|
createIsEqual,
|
|
6
|
-
} from './comparator';
|
|
7
|
-
import type { CustomEqualCreatorOptions } from './internalTypes';
|
|
8
|
-
import { sameValueZeroEqual } from './utils';
|
|
6
|
+
} from './comparator.ts';
|
|
7
|
+
import type { CustomEqualCreatorOptions } from './internalTypes.ts';
|
|
8
|
+
import { sameValueZeroEqual } from './utils.ts';
|
|
9
9
|
|
|
10
10
|
export { sameValueZeroEqual };
|
|
11
11
|
export type {
|
|
@@ -25,7 +25,7 @@ export type {
|
|
|
25
25
|
State,
|
|
26
26
|
TypeEqualityComparator,
|
|
27
27
|
TypedArray,
|
|
28
|
-
} from './internalTypes';
|
|
28
|
+
} from './internalTypes.ts';
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
31
|
* Whether the items passed are deeply-equal in value.
|
package/src/internalTypes.ts
CHANGED
|
@@ -142,7 +142,7 @@ export type InternalEqualityComparator<Meta> = (
|
|
|
142
142
|
) => boolean;
|
|
143
143
|
|
|
144
144
|
// We explicitly check for primitive wrapper types
|
|
145
|
-
// eslint-disable-next-line @typescript-eslint/
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/no-wrapper-object-types
|
|
146
146
|
export type PrimitiveWrapper = Boolean | Number | String;
|
|
147
147
|
|
|
148
148
|
/**
|
package/src/utils.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
Dictionary,
|
|
6
6
|
State,
|
|
7
7
|
TypeEqualityComparator,
|
|
8
|
-
} from './internalTypes';
|
|
8
|
+
} from './internalTypes.ts';
|
|
9
9
|
|
|
10
10
|
const { getOwnPropertyNames, getOwnPropertySymbols } = Object;
|
|
11
11
|
const { hasOwnProperty } = Object.prototype;
|
|
@@ -83,6 +83,7 @@ export function getStrictProperties(
|
|
|
83
83
|
* Whether the object contains the property passed as an own property.
|
|
84
84
|
*/
|
|
85
85
|
export const hasOwn =
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
86
87
|
Object.hasOwn ||
|
|
87
88
|
((object: Dictionary, property: number | string | symbol) =>
|
|
88
89
|
hasOwnProperty.call(object, property));
|
package/.babelrc
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"env": {
|
|
3
|
-
"lib": {
|
|
4
|
-
"presets": [
|
|
5
|
-
[
|
|
6
|
-
"@babel/preset-env",
|
|
7
|
-
{
|
|
8
|
-
"loose": true
|
|
9
|
-
}
|
|
10
|
-
]
|
|
11
|
-
]
|
|
12
|
-
},
|
|
13
|
-
"test": {
|
|
14
|
-
"presets": [
|
|
15
|
-
[
|
|
16
|
-
"@babel/preset-env",
|
|
17
|
-
{
|
|
18
|
-
"loose": true
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
]
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"presets": [
|
|
25
|
-
"@babel/preset-typescript",
|
|
26
|
-
[
|
|
27
|
-
"@babel/preset-env",
|
|
28
|
-
{
|
|
29
|
-
"loose": true,
|
|
30
|
-
"modules": false
|
|
31
|
-
}
|
|
32
|
-
]
|
|
33
|
-
]
|
|
34
|
-
}
|
package/.prettierrc
DELETED
package/.release-it.beta.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"github": {
|
|
3
|
-
"release": true,
|
|
4
|
-
"tagName": "v${version}"
|
|
5
|
-
},
|
|
6
|
-
"hooks": {
|
|
7
|
-
"before:init": [
|
|
8
|
-
"npm run typecheck",
|
|
9
|
-
"npm run lint",
|
|
10
|
-
"npm run test",
|
|
11
|
-
"npm run build"
|
|
12
|
-
]
|
|
13
|
-
},
|
|
14
|
-
"npm": {
|
|
15
|
-
"tag": "next"
|
|
16
|
-
},
|
|
17
|
-
"preReleaseId": "beta"
|
|
18
|
-
}
|
package/.release-it.json
DELETED
package/.yarnrc.yml
DELETED
package/BUILD.md
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# Reproducing a build
|
|
2
|
-
|
|
3
|
-
## Clone version
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
git clone https://github.com/planttheidea/fast-equals.git
|
|
7
|
-
cd fast-equals
|
|
8
|
-
git checkout {version}
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Replace `{version}` above with the appropriate package version. If you want to compare a version older than `1.6.2`, you'll need to use a commit hash directly.
|
|
12
|
-
|
|
13
|
-
## Install
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
yarn install
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
We use `yarn` for our package management, so to ensure that exact dependencies you should also use it.
|
|
20
|
-
|
|
21
|
-
## Build artifacts
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
yarn run build
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
**NOTE**: To get an exact checksum match with the versions released on npm, it may be necessary to change line endings. For example, on Linux you might run:
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
unix2dos dist/fast-equals.min.js
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Get checksum
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
sha256sum dist/fast-equals.min.js
|
|
37
|
-
```
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import commonjs from '@rollup/plugin-commonjs';
|
|
2
|
-
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
3
|
-
import replace from '@rollup/plugin-replace';
|
|
4
|
-
import typescript from '@rollup/plugin-typescript';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import tsc from 'typescript';
|
|
8
|
-
import { fileURLToPath } from 'url';
|
|
9
|
-
|
|
10
|
-
const ROOT = fileURLToPath(new URL('../..', import.meta.url));
|
|
11
|
-
|
|
12
|
-
export const PACKAGE_JSON = JSON.parse(
|
|
13
|
-
fs.readFileSync(path.resolve(ROOT, 'package.json')),
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
const external = [
|
|
17
|
-
...Object.keys(PACKAGE_JSON.dependencies || {}),
|
|
18
|
-
...Object.keys(PACKAGE_JSON.peerDependencies || {}),
|
|
19
|
-
];
|
|
20
|
-
const globals = external.reduce((globals, name) => {
|
|
21
|
-
globals[name] = name;
|
|
22
|
-
|
|
23
|
-
return globals;
|
|
24
|
-
}, {});
|
|
25
|
-
|
|
26
|
-
export const BASE_CONFIG = {
|
|
27
|
-
external,
|
|
28
|
-
input: path.resolve(ROOT, 'src', 'index.ts'),
|
|
29
|
-
output: {
|
|
30
|
-
exports: 'named',
|
|
31
|
-
globals,
|
|
32
|
-
name: 'fast-equals',
|
|
33
|
-
sourcemap: true,
|
|
34
|
-
},
|
|
35
|
-
plugins: [
|
|
36
|
-
replace({
|
|
37
|
-
'process.env.NODE_ENV': JSON.stringify('production'),
|
|
38
|
-
preventAssignment: true,
|
|
39
|
-
}),
|
|
40
|
-
nodeResolve({
|
|
41
|
-
mainFields: ['module', 'browser', 'main'],
|
|
42
|
-
}),
|
|
43
|
-
commonjs({ include: /use-sync-external-store/ }),
|
|
44
|
-
typescript({
|
|
45
|
-
tsconfig: path.resolve(ROOT, 'config', 'tsconfig', 'base.json'),
|
|
46
|
-
typescript: tsc,
|
|
47
|
-
}),
|
|
48
|
-
],
|
|
49
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { BASE_CONFIG, PACKAGE_JSON } from './config.base.js';
|
|
2
|
-
import terser from '@rollup/plugin-terser';
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
...BASE_CONFIG,
|
|
6
|
-
output: {
|
|
7
|
-
...BASE_CONFIG.output,
|
|
8
|
-
file: PACKAGE_JSON.browser.replace('umd', 'min'),
|
|
9
|
-
format: 'umd',
|
|
10
|
-
sourcemap: false,
|
|
11
|
-
},
|
|
12
|
-
plugins: [...BASE_CONFIG.plugins, terser()],
|
|
13
|
-
};
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"allowJs": true,
|
|
4
|
-
"allowUnreachableCode": false,
|
|
5
|
-
"baseUrl": "../../src",
|
|
6
|
-
"esModuleInterop": true,
|
|
7
|
-
"jsx": "react-jsx",
|
|
8
|
-
"lib": ["DOM", "ESNext"],
|
|
9
|
-
"module": "ESNext",
|
|
10
|
-
"moduleResolution": "Node",
|
|
11
|
-
"noFallthroughCasesInSwitch": true,
|
|
12
|
-
"noImplicitAny": true,
|
|
13
|
-
"noImplicitReturns": true,
|
|
14
|
-
"noImplicitThis": true,
|
|
15
|
-
"noUncheckedIndexedAccess": true,
|
|
16
|
-
"noUnusedLocals": true,
|
|
17
|
-
"noUnusedParameters": true,
|
|
18
|
-
"outDir": "../../../dist",
|
|
19
|
-
"resolveJsonModule": true,
|
|
20
|
-
"skipLibCheck": true,
|
|
21
|
-
"sourceMap": true,
|
|
22
|
-
"strict": true,
|
|
23
|
-
"strictBindCallApply": true,
|
|
24
|
-
"strictNullChecks": true,
|
|
25
|
-
"inlineSources": true,
|
|
26
|
-
"target": "es5",
|
|
27
|
-
"types": ["jest", "node", "react"]
|
|
28
|
-
},
|
|
29
|
-
"exclude": ["../../node_modules"],
|
|
30
|
-
"include": ["../../src/**/*", "../../__tests__/**/*", "../../DEV_ONLY/**/*"],
|
|
31
|
-
"files": ["../../node_modules/jest-expect-message/types/index.d.ts"]
|
|
32
|
-
}
|
package/config/tsconfig/cjs.json
DELETED
package/config/tsconfig/esm.json
DELETED
package/config/tsconfig/min.json
DELETED
package/config/tsconfig/umd.json
DELETED
package/config/webpack.config.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
2
|
-
|
|
3
|
-
import ESLintWebpackPlugin from 'eslint-webpack-plugin';
|
|
4
|
-
import HtmlWebpackPlugin from 'html-webpack-plugin';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
import webpack from 'webpack';
|
|
8
|
-
|
|
9
|
-
const ROOT = fileURLToPath(new URL('..', import.meta.url));
|
|
10
|
-
const PORT = 3000;
|
|
11
|
-
|
|
12
|
-
export default {
|
|
13
|
-
cache: true,
|
|
14
|
-
|
|
15
|
-
devServer: {
|
|
16
|
-
host: 'localhost',
|
|
17
|
-
port: PORT,
|
|
18
|
-
},
|
|
19
|
-
|
|
20
|
-
devtool: 'source-map',
|
|
21
|
-
|
|
22
|
-
entry: [path.resolve(ROOT, 'DEV_ONLY', 'index.tsx')],
|
|
23
|
-
|
|
24
|
-
mode: 'development',
|
|
25
|
-
|
|
26
|
-
module: {
|
|
27
|
-
rules: [
|
|
28
|
-
{
|
|
29
|
-
include: [path.resolve(ROOT, 'src'), path.resolve(ROOT, 'DEV_ONLY')],
|
|
30
|
-
loader: 'ts-loader',
|
|
31
|
-
options: {
|
|
32
|
-
reportFiles: ['src/*.{ts|tsx}'],
|
|
33
|
-
},
|
|
34
|
-
test: /\.(ts|tsx)$/,
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
output: {
|
|
40
|
-
filename: 'fast-equals.js',
|
|
41
|
-
library: 'fastEquals',
|
|
42
|
-
libraryTarget: 'umd',
|
|
43
|
-
path: path.resolve(ROOT, 'dist'),
|
|
44
|
-
publicPath: `http://localhost:${PORT}/`,
|
|
45
|
-
umdNamedDefine: true,
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
plugins: [
|
|
49
|
-
new ESLintWebpackPlugin(),
|
|
50
|
-
new webpack.EnvironmentPlugin(['NODE_ENV']),
|
|
51
|
-
new HtmlWebpackPlugin(),
|
|
52
|
-
],
|
|
53
|
-
|
|
54
|
-
resolve: {
|
|
55
|
-
extensions: ['.tsx', '.ts', '.js'],
|
|
56
|
-
},
|
|
57
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# Explicit property check
|
|
2
|
-
|
|
3
|
-
Sometimes it is necessary to squeeze every once of performance out of your runtime code, and deep equality checks can be a bottleneck. When this is occurs, it can be advantageous to build a custom comparison that allows for highly specific equality checks.
|
|
4
|
-
|
|
5
|
-
An example where you know the shape of the objects being passed in, where the `foo` property is a simple primitive and the `bar` property is a nested object:
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { createCustomEqual } from 'fast-equals';
|
|
9
|
-
import type { TypeEqualityComparator } from 'fast-equals';
|
|
10
|
-
|
|
11
|
-
interface SpecialObject {
|
|
12
|
-
foo: string;
|
|
13
|
-
bar: {
|
|
14
|
-
baz: number;
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const areObjectsEqual: TypeEqualityComparator<SpecialObject, undefined> = (
|
|
19
|
-
a,
|
|
20
|
-
b,
|
|
21
|
-
) => a.foo === b.foo && a.bar.baz === b.bar.baz;
|
|
22
|
-
|
|
23
|
-
const isSpecialObjectEqual = createCustomEqual({
|
|
24
|
-
createCustomConfig: () => ({ areObjectsEqual }),
|
|
25
|
-
});
|
|
26
|
-
```
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Legacy environment support for circular equal comparators
|
|
2
|
-
|
|
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 and polyfilling is not an option, creating a custom comparator that uses a custom cache implementation with the same contract is a simple solution.
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
import { createCustomEqual, sameValueZeroEqual } from 'fast-equals';
|
|
7
|
-
import type { Cache } from 'fast-equals';
|
|
8
|
-
|
|
9
|
-
function getCache(): Cache<any, any> {
|
|
10
|
-
const entries: Array<[object, any]> = [];
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
delete(key) {
|
|
14
|
-
for (let index = 0; index < entries.length; ++index) {
|
|
15
|
-
if (entries[index][0] === key) {
|
|
16
|
-
entries.splice(index, 1);
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
return false;
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
get(key) {
|
|
25
|
-
for (let index = 0; index < entries.length; ++index) {
|
|
26
|
-
if (entries[index][0] === key) {
|
|
27
|
-
return entries[index][1];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
set(key, value) {
|
|
33
|
-
for (let index = 0; index < entries.length; ++index) {
|
|
34
|
-
if (entries[index][0] === key) {
|
|
35
|
-
entries[index][1] = value;
|
|
36
|
-
return this;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
entries.push([key, value]);
|
|
41
|
-
|
|
42
|
-
return this;
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface Meta {
|
|
48
|
-
customMethod(): void;
|
|
49
|
-
customValue: string;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const meta = {
|
|
53
|
-
customMethod() {
|
|
54
|
-
console.log('hello!');
|
|
55
|
-
},
|
|
56
|
-
customValue: 'goodbye',
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
const circularDeepEqual = createCustomEqual<Cache>({
|
|
60
|
-
circular: true,
|
|
61
|
-
createState: () => ({
|
|
62
|
-
cache: getCache(),
|
|
63
|
-
meta,
|
|
64
|
-
}),
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const circularShallowEqual = createCustomEqual<Cache>({
|
|
68
|
-
circular: true,
|
|
69
|
-
comparator: sameValueZeroEqual,
|
|
70
|
-
createState: () => ({
|
|
71
|
-
cache: getCache(),
|
|
72
|
-
meta,
|
|
73
|
-
}),
|
|
74
|
-
});
|
|
75
|
-
```
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# Legacy environment support for `RegExp` comparators
|
|
2
|
-
|
|
3
|
-
Starting in `4.x.x`, `RegExp.prototype.flags` is expected to be available in the environment. All modern browsers support this feature, however there may be situations where a legacy environmental support is required (example: IE11). If you need to support such an environment and polyfilling is not an option, creating a custom comparator that uses a more verbose comparison of all possible flags is a simple solution.
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
import { createCustomEqual, sameValueZeroEqual } from 'deep-Equals';
|
|
7
|
-
|
|
8
|
-
const areRegExpsEqual = (a: RegExp, b: RegExp) =>
|
|
9
|
-
a.source === b.source &&
|
|
10
|
-
a.global === b.global &&
|
|
11
|
-
a.ignoreCase === b.ignoreCase &&
|
|
12
|
-
a.multiline === b.multiline &&
|
|
13
|
-
a.unicode === b.unicode &&
|
|
14
|
-
a.sticky === b.sticky &&
|
|
15
|
-
a.lastIndex === b.lastIndex;
|
|
16
|
-
|
|
17
|
-
const deepEqual = createCustomEqual({
|
|
18
|
-
createCustomConfig: () => ({ areRegExpsEqual }),
|
|
19
|
-
});
|
|
20
|
-
const shallowEqual = createCustomEqual({
|
|
21
|
-
comparator: sameValueZero,
|
|
22
|
-
createCustomConfig: () => ({ areRegExpsEqual }),
|
|
23
|
-
});
|
|
24
|
-
```
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# Non-standard properties
|
|
2
|
-
|
|
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.
|
|
4
|
-
|
|
5
|
-
```ts
|
|
6
|
-
import { createCustomEqual } from 'fast-equals';
|
|
7
|
-
import type { TypeEqualityComparator } from 'fast-equals';
|
|
8
|
-
|
|
9
|
-
type AreObjectsEqual = TypeEqualityComparator<Record<any, any>, undefined>;
|
|
10
|
-
|
|
11
|
-
class HiddenProperty {
|
|
12
|
-
visible: boolean;
|
|
13
|
-
#hidden: string;
|
|
14
|
-
|
|
15
|
-
constructor(value: string) {
|
|
16
|
-
this.visible = true;
|
|
17
|
-
this.#hidden = value;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
get hidden() {
|
|
21
|
-
return this.#hidden;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function createAreObjectsEqual(
|
|
26
|
-
areObjectsEqual: AreObjectsEqual,
|
|
27
|
-
): AreObjectsEqual {
|
|
28
|
-
return function (a, b, state) {
|
|
29
|
-
if (!areObjectsEqual(a, b, state)) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const aInstance = a instanceof HiddenProperty;
|
|
34
|
-
const bInstance = b instanceof HiddenProperty;
|
|
35
|
-
|
|
36
|
-
if (aInstance || bInstance) {
|
|
37
|
-
return aInstance && bInstance && a.hidden === b.hidden;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return true;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const deepEqual = createCustomEqual({
|
|
45
|
-
createCustomConfig: ({ areObjectsEqual }) =>
|
|
46
|
-
createAreObjectsEqual(areObjectsEqual),
|
|
47
|
-
});
|
|
48
|
-
```
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Handling special (built-in) objects
|
|
2
|
-
|
|
3
|
-
The `createCustomEqual` uses `@@toStringTag` to decide which well-known comparator to call. However, some values might not fit either of them. For example `WeakMap` is compared intentionally. Additionally, it's possible that new built-in objects are added to the language. Third parties might also add `@@toStringTag` to their objects.
|
|
4
|
-
|
|
5
|
-
For example the [TC39 Temporal spec](https://tc39.es/proposal-temporal/docs/) requires `@@toStringTag` being implemetend and the polyfills do that. Passing `areObjectsEqual` will not work in that scenario. Instead you'll have to register a handler for the tag instead.
|
|
6
|
-
|
|
7
|
-
```ts
|
|
8
|
-
import { createCustomEqual } from 'fast-equals';
|
|
9
|
-
import type { TypeEqualityComparator } from 'fast-equals';
|
|
10
|
-
|
|
11
|
-
const areZonedDateTimesEqual: TypeEqualityComparator<unknown, undefined> = (
|
|
12
|
-
a,
|
|
13
|
-
b,
|
|
14
|
-
) => a instanceof Temporal.ZonedDateTime
|
|
15
|
-
&& b instanceof Temporal.ZonedDateTime
|
|
16
|
-
&& a.equals(b);
|
|
17
|
-
|
|
18
|
-
const isSpecialObjectEqual = createCustomEqual({
|
|
19
|
-
createCustomConfig: () => ({
|
|
20
|
-
unknownTagComparators: {
|
|
21
|
-
"Temporal.ZonedDateTime", areZonedDateTimesEqual,
|
|
22
|
-
}
|
|
23
|
-
}),
|
|
24
|
-
});
|
|
25
|
-
```
|