### Install fast-equals Source: https://context7.com/planttheidea/fast-equals/llms.txt Install the library using npm. You can also import specific builds for ESM or CommonJS. ```bash npm install fast-equals ``` ```typescript // ESM import { deepEqual } from 'fast-equals'; // CommonJS const { deepEqual } = require('fast-equals'); // Force a specific build import { deepEqual } from 'fast-equals/dist/es/index.mjs'; // ESM import { deepEqual } from 'fast-equals/dist/cjs/index.cjs'; // CJS ``` -------------------------------- ### Usage Example Source: https://github.com/planttheidea/fast-equals/blob/main/README.md A basic example demonstrating how to import and use the `deepEqual` function from the fast-equals library. ```APIDOC ## Usage Example ### Description A basic example demonstrating how to import and use the `deepEqual` function from the fast-equals library. ### Code ```ts import { deepEqual } from 'fast-equals'; console.log(deepEqual({ foo: 'bar' }, { foo: 'bar' })); // true ``` ``` -------------------------------- ### Install Dependencies with Yarn Source: https://github.com/planttheidea/fast-equals/blob/main/BUILD.md Install project dependencies using Yarn. It is recommended to use Yarn for package management to ensure exact dependency versions. ```bash yarn install ``` -------------------------------- ### Deep Equality Comparison Example Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Demonstrates the difference between strict equality (===) and deep equality using fast-equals. Use deepEqual when you need to compare the contents of objects, not just their references. ```typescript import { deepEqual } from 'fast-equals'; const objectA = { foo: { bar: 'baz' } }; const objectB = { foo: { bar: 'baz' } }; console.log(objectA === objectB); // false console.log(deepEqual(objectA, objectB)); // true ``` -------------------------------- ### Comparing Non-Standard/Hidden Properties with WeakMap Source: https://context7.com/planttheidea/fast-equals/llms.txt Use `createCustomEqual` with `createCustomConfig` to define a custom object equality comparator. This example compares instances of a `Token` class, using a `WeakMap` to access hidden properties. ```typescript import { createCustomEqual } from 'fast-equals'; import type { EqualityComparator } from 'fast-equals'; const hiddenRefs = new WeakMap(); class Token { visible = true; constructor(secret: string) { hiddenRefs.set(this, secret); } } const deepEqualWithHidden = createCustomEqual({ createCustomConfig: ({ areObjectsEqual }) => ({ areObjectsEqual: ((a, b, state) => { if (!areObjectsEqual(a, b, state)) return false; if (a instanceof Token && b instanceof Token) { return hiddenRefs.get(a) === hiddenRefs.get(b); } return true; }) as EqualityComparator, }), }); const t1 = new Token('secret-abc'); const t2 = new Token('secret-abc'); const t3 = new Token('secret-xyz'); deepEqualWithHidden(t1, t2); // true deepEqualWithHidden(t1, t3); // false ``` -------------------------------- ### Custom Cache for Circular Equality in Legacy Environments Source: https://context7.com/planttheidea/fast-equals/llms.txt Implement a custom cache using `createState` with `circular: true` for handling circular references in older JavaScript environments. This example uses a simple array-based cache. ```typescript import { createCustomEqual } from 'fast-equals'; import type { Cache } from 'fast-equals'; function arrayCache(): Cache { const entries: Array<[object, any]> = []; return { delete(key) { const i = entries.findIndex(([k]) => k === key); if (i !== -1) { entries.splice(i, 1); return true; } return false; }, get(key) { return entries.find(([k]) => k === key)?.[1]; }, set(key, value) { const i = entries.findIndex(([k]) => k === key); if (i !== -1) entries[i][1] = value; else entries.push([key, value]); return this; }, }; } const circularDeepEqualLegacy = createCustomEqual({ circular: true, createState: () => ({ cache: arrayCache() }), }); const a: any = { foo: 'bar' }; a.self = a; const b: any = { foo: 'bar' }; b.self = b; circularDeepEqualLegacy(a, b); // true ``` -------------------------------- ### Custom Cache Implementation for Circular Equality Source: https://github.com/planttheidea/fast-equals/blob/main/recipes/legacy-circular-equal-support.md Implements a custom cache using an array of entries to support circular equality checks in environments lacking `WeakMap`. This provides the necessary `delete`, `get`, and `set` methods. ```typescript import { createCustomEqual, sameValueEqual, } from 'fast-equals'; import type { Cache } from 'fast-equals'; function getCache(): Cache { const entries: Array<[object, any]> = []; return { delete(key) { for (let index = 0; index < entries.length; ++index) { if (entries[index][0] === key) { entries.splice(index, 1); return true; } } return false; }, get(key) { for (let index = 0; index < entries.length; ++index) { if (entries[index][0] === key) { return entries[index][1]; } } }, set(key, value) { for (let index = 0; index < entries.length; ++index) { if (entries[index][0] === key) { entries[index][1] = value; return this; } } entries.push([key, value]); return this; }, }; } interface Meta { customMethod(): void; customValue: string; } const meta = { customMethod() { console.log('hello!'); }, customValue: 'goodbye', }; const circularDeepEqual = createCustomEqual({ circular: true, createState: () => ({ cache: getCache(), meta, }), }); const circularShallowEqual = createCustomEqual({ circular: true, comparator: sameValueEqual, createState: () => ({ cache: getCache(), meta, }), }); ``` -------------------------------- ### Shallow Equality Comparison Example Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Use shallowEqual to compare objects based only on their own properties, without recursing into nested objects. This is useful for performance-sensitive scenarios or when only the top-level properties need to match. ```typescript import { shallowEqual } from 'fast-equals'; const nestedObject = { bar: 'baz' }; const objectA = { foo: nestedObject }; const objectB = { foo: nestedObject }; const objectC = { foo: { bar: 'baz' } }; console.log(objectA === objectB); // false console.log(shallowEqual(objectA, objectB)); // true console.log(shallowEqual(objectA, objectC)); // false ``` -------------------------------- ### Clone fast-equals Repository Source: https://github.com/planttheidea/fast-equals/blob/main/BUILD.md Clone the repository and checkout a specific version. Replace `{version}` with the desired package version. For versions older than 1.6.2, use a commit hash. ```bash git clone https://github.com/planttheidea/fast-equals.git cd fast-equals git checkout {version} ``` -------------------------------- ### sameValueZeroEqual Source: https://context7.com/planttheidea/fast-equals/llms.txt Implements the `SameValueZero` algorithm. `NaN === NaN` is `true`, and `+0 === -0` is also `true`. This matches the behavior of `Map`/`Set` key lookups. ```APIDOC ## sameValueZeroEqual ### Description Implements the [SameValueZero](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) algorithm: `NaN === NaN` is `true`, but `+0 === -0` is also `true` (unlike `sameValueEqual`). This matches the behavior of `Map`/`Set` key lookups. ### Method `sameValueZeroEqual(value: any, other: any): boolean` ### Parameters - **value**: The first value to compare. - **other**: The second value to compare. ### Request Example ```javascript import { sameValueZeroEqual } from 'fast-equals'; console.log(sameValueZeroEqual(NaN, NaN)); // true console.log(sameValueZeroEqual(+0, -0)); // true console.log(sameValueZeroEqual(1, 1)); // true console.log(sameValueZeroEqual('a', 'b')); // false console.log(sameValueZeroEqual({}, {})); // false ``` ### Response - **boolean**: `true` if the values are same-value-zero equal, `false` otherwise. ``` -------------------------------- ### Build Project Artifacts Source: https://github.com/planttheidea/fast-equals/blob/main/BUILD.md Build the project artifacts using the Yarn build script. ```bash yarn run build ``` -------------------------------- ### SameValueZero Equality Comparison Source: https://context7.com/planttheidea/fast-equals/llms.txt Use `sameValueZeroEqual` to implement the `SameValueZero` algorithm, where `NaN` equals `NaN` and `+0` equals `-0`. This matches `Map` and `Set` key comparison behavior. ```typescript import { sameValueZeroEqual } from 'fast-equals'; sameValueZeroEqual(NaN, NaN); // true sameValueZeroEqual(+0, -0); // true (differs from sameValueEqual) sameValueZeroEqual(1, 1); // true sameValueZeroEqual('a', 'b'); // false sameValueZeroEqual({}, {}); // false — referential equality only ``` -------------------------------- ### Benchmark Results Table Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Displays the performance of fast-equals and other deep equality libraries in operations per second for various object types. Note that some libraries may fail on specific object types or equality checks. ```bash ┌────────────────────────────────────────┬────────────────┐ │ Name │ Ops / sec │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (passed) │ 1544237.29413 │ ├────────────────────────────────────────┼────────────────┤ │ fast-deep-equal (passed) │ 1328583.767745 │ ├────────────────────────────────────────┼────────────────┤ │ react-fast-compare (passed) │ 1301727.296375 │ ├────────────────────────────────────────┼────────────────┤ │ shallow-equal-fuzzy (passed) │ 1225981.400919 │ ├────────────────────────────────────────┼────────────────┤ │ nano-equal (failed) │ 969495.538753 │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (circular) (passed) │ 813716.49516 │ ├────────────────────────────────────────┼────────────────┤ │ dequal/lite (passed) │ 780805.627339 │ ├────────────────────────────────────────┼────────────────┤ │ dequal (passed) │ 767208.995048 │ ├────────────────────────────────────────┼────────────────┤ │ underscore.isEqual (passed) │ 490695.830468 │ ├────────────────────────────────────────┼────────────────┤ │ assert.deepStrictEqual (passed) │ 471011.425391 │ ├────────────────────────────────────────┼────────────────┤ │ lodash.isEqual (passed) │ 296064.057382 │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (strict) (passed) │ 225894.800964 │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (strict circular) (passed) │ 195657.732354 │ ├────────────────────────────────────────┼────────────────┤ │ deep-eql (passed) │ 162718.102328 │ ├────────────────────────────────────────┼────────────────┤ │ deep-equal (passed) │ 954.172311 │ └────────────────────────────────────────┴────────────────┘ ``` ```bash Testing mixed objects not equal... ┌────────────────────────────────────────┬────────────────┐ │ Name │ Ops / sec │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (passed) │ 5112341.000979 │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (circular) (passed) │ 3501225.300307 │ ├────────────────────────────────────────┼────────────────┤ │ fast-deep-equal (passed) │ 3471838.735181 │ ├────────────────────────────────────────┼────────────────┤ │ react-fast-compare (passed) │ 3439612.908273 │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (strict) (passed) │ 1797319.423491 │ ├────────────────────────────────────────┼────────────────┤ │ fast-equals (strict circular) (passed) │ 1534168.229167 │ ├────────────────────────────────────────┼────────────────┤ │ dequal/lite (passed) │ 1357981.758571 │ ├────────────────────────────────────────┼────────────────┤ │ dequal (passed) │ 1328078.173967 │ ├────────────────────────────────────────┼────────────────┤ │ shallow-equal-fuzzy (failed) │ 1224747.272118 │ ├────────────────────────────────────────┼────────────────┤ │ nano-equal (passed) │ 1087373.99615 │ ├────────────────────────────────────────┼────────────────┤ │ underscore.isEqual (passed) │ 927298.592729 │ ├────────────────────────────────────────┼────────────────┤ │ lodash.isEqual (passed) │ 387294.235476 │ ├────────────────────────────────────────┼────────────────┤ │ deep-eql (passed) │ 186028.168827 │ ├────────────────────────────────────────┼────────────────┤ │ assert.deepStrictEqual (passed) │ 21261.312424 │ ├────────────────────────────────────────┼────────────────┤ │ deep-equal (passed) │ 3782.329948 │ └────────────────────────────────────────┴────────────────┘ ``` -------------------------------- ### `createCustomEqual` Source: https://context7.com/planttheidea/fast-equals/llms.txt A factory function that allows the creation of custom equality comparators. It accepts an options object to override specific aspects of the comparison process, such as circular reference handling, strictness, or custom logic for comparing specific types. ```APIDOC ## `createCustomEqual` ### Description Factory function that creates a bespoke equality comparator. Accepts an options object to override any aspect of the comparison pipeline. All built-in comparators (`deepEqual`, `shallowEqual`, etc.) are themselves built with this factory. ### Options - `circular` (boolean): Enable or disable circular reference checking. - `createCustomConfig` (function): A function that returns a partial `ComparatorConfig` to override default comparison logic for specific types. - `createInternalComparator` (function): A function to create a custom internal comparator. - `createState` (function): A function to create custom state for the comparator, such as a cache or metadata. - `strict` (boolean): Enable or disable strict property descriptor checks. ### Usage Example: Overriding a specific type comparator ```ts import { createCustomEqual } from 'fast-equals'; interface SpecialObject { foo: string; bar: { baz: number }; } // Hot-path: compare only the fields you care about, skip full recursion const isSpecialObjectEqual = createCustomEqual({ createCustomConfig: () => ({ areObjectsEqual: (a: SpecialObject, b: SpecialObject) => a.foo === b.foo && a.bar.baz === b.bar.baz, }), }); isSpecialObjectEqual({ foo: 'x', bar: { baz: 1 } }, { foo: 'x', bar: { baz: 1 } }); // true isSpecialObjectEqual({ foo: 'x', bar: { baz: 1 } }, { foo: 'x', bar: { baz: 2 } }); // false ``` ``` -------------------------------- ### Injecting External Meta State for Wildcard Comparison Source: https://context7.com/planttheidea/fast-equals/llms.txt Use `createCustomEqual` with `createState` to inject external meta-state, enabling wildcard matching in comparisons. Useful when a specific value should be treated as a wildcard. ```typescript import { createCustomEqual } from 'fast-equals'; interface Meta { wildcard: string } const meta: Meta = { wildcard: 'ANY' }; const wildcardDeepEqual = createCustomEqual({ createInternalComparator: (compare) => (a, b, _keyA, _keyB, _parentA, _parentB, state) => compare(a, b, state) || a === state.meta.wildcard || b === state.meta.wildcard, createState: () => ({ meta }), }); wildcardDeepEqual({ x: 'ANY' }, { x: 'something' }); // true — 'ANY' is wildcard wildcardDeepEqual({ x: 'foo' }, { x: 'bar' }); // false ``` -------------------------------- ### Legacy RegExp Comparison without RegExp.prototype.flags Source: https://context7.com/planttheidea/fast-equals/llms.txt Define a custom `areRegExpsEqual` function and pass it to `createCustomEqual` via `createCustomConfig` to handle `RegExp` comparisons in environments lacking `RegExp.prototype.flags`. This ensures accurate comparison based on source and flags. ```typescript import { createCustomEqual } from 'fast-equals'; const areRegExpsEqual = (a: RegExp, b: RegExp) => a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline && a.unicode === b.unicode && a.sticky === b.sticky && a.lastIndex === b.lastIndex; const deepEqual = createCustomEqual({ createCustomConfig: () => ({ areRegExpsEqual }), }); deepEqual(/foo/gi, /foo/gi); // true deepEqual(/foo/g, /foo/i); // false ``` -------------------------------- ### Generate SHA256 Checksum Source: https://github.com/planttheidea/fast-equals/blob/main/BUILD.md Generate the SHA256 checksum for the built artifact to verify its integrity. ```bash sha256sum dist/fast-equals.min.js ``` -------------------------------- ### sameValueEqual Source: https://context7.com/planttheidea/fast-equals/llms.txt A ponyfill for `Object.is`. Treats `NaN === NaN` as `true` and `+0 === -0` as `false`. In environments that support it, this is simply a re-export of `Object.is`. ```APIDOC ## sameValueEqual ### Description A ponyfill for [`Object.is`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is). In environments that support it, this is simply a re-export of `Object.is`. Treats `NaN === NaN` as `true` and `+0 === -0` as `false`. ### Method `sameValueEqual(value: any, other: any): boolean` ### Parameters - **value**: The first value to compare. - **other**: The second value to compare. ### Request Example ```javascript import { sameValueEqual } from 'fast-equals'; console.log(sameValueEqual(NaN, NaN)); // true console.log(sameValueEqual(+0, -0)); // false console.log(sameValueEqual(1, 1)); // true console.log(sameValueEqual('a', 'b')); // false console.log(sameValueEqual(null, null)); // true console.log(sameValueEqual({}, {})); // false ``` ### Response - **boolean**: `true` if the values are same-value equal, `false` otherwise. ``` -------------------------------- ### Create Custom Equality Comparator Source: https://context7.com/planttheidea/fast-equals/llms.txt A factory function to create bespoke equality comparators. It accepts an options object to customize aspects of the comparison pipeline, allowing for overrides of specific type comparators. ```typescript function createCustomEqual(options?: { circular?: boolean; createCustomConfig?: (defaultConfig: ComparatorConfig) => Partial>; createInternalComparator?: ( compare: EqualityComparator ) => InternalEqualityComparator; createState?: () => { cache?: Cache; meta?: Meta }; strict?: boolean; }): (a: A, b: B) => boolean; ``` ```typescript import { createCustomEqual } from 'fast-equals'; interface SpecialObject { foo: string; bar: { baz: number }; } // Hot-path: compare only the fields you care about, skip full recursion const isSpecialObjectEqual = createCustomEqual({ createCustomConfig: () => ({ areObjectsEqual: (a: SpecialObject, b: SpecialObject) => a.foo === b.foo && a.bar.baz === b.bar.baz, }), }); isSpecialObjectEqual({ foo: 'x', bar: { baz: 1 } }, { foo: 'x', bar: { baz: 1 } }); // true isSpecialObjectEqual({ foo: 'x', bar: { baz: 1 } }, { foo: 'x', bar: { baz: 2 } }); // false ``` -------------------------------- ### Custom Comparator for Specific Object Tags (e.g., Temporal) Source: https://context7.com/planttheidea/fast-equals/llms.txt Leverage `createCustomEqual` with `getUnsupportedCustomComparator` to provide custom comparison logic for objects identified by their `Symbol.toStringTag`. This is useful for custom or polyfilled objects like `Temporal.ZonedDateTime`. ```typescript import { createCustomEqual } from 'fast-equals'; // Example: Temporal.ZonedDateTime polyfill or proposal object const isEqual = createCustomEqual({ createCustomConfig: () => ({ getUnsupportedCustomComparator(a: any) { if (a?.[Symbol.toStringTag] === 'Temporal.ZonedDateTime') { return (x: any, y: any) => x instanceof Temporal.ZonedDateTime && y instanceof Temporal.ZonedDateTime && x.equals(y); } }, }), }); ``` -------------------------------- ### Import and Use deepEqual Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Import the deepEqual function from the 'fast-equals' library to perform deep equality comparisons. This is useful for checking if two objects have the same structure and values recursively. ```typescript import { deepEqual } from 'fast-equals'; console.log(deepEqual({ foo: 'bar' }, { foo: 'bar' })); // true ``` -------------------------------- ### Custom Comparator with Meta State Source: https://github.com/planttheidea/fast-equals/blob/main/recipes/using-meta-in-comparison.md Define a custom equality function that uses meta state. The `createInternalComparator` receives a `compare` function and returns a comparator that checks the meta value. The `createState` function initializes the meta object. ```typescript import { createCustomEqual } from 'fast-equals'; interface Meta { value: string; } const meta: Meta = { value: 'baz' }; const deepEqual = createCustomEqual({ createInternalComparator: (compare) => (a, b, _keyA, _keyB, _parentA, _parentB, state) => compare(a, b, state) || a === state.meta.value || b === state.meta.value, createState: () => ({ meta }), }); ``` -------------------------------- ### `strictShallowEqual` Source: https://context7.com/planttheidea/fast-equals/llms.txt Performs a shallow equality check with strict property descriptor checks, similar to `strictDeepEqual`. It compares top-level properties while also considering strictness in property descriptors. ```APIDOC ## `strictShallowEqual` ### Description Shallow equality with the same strict property descriptor checks as `strictDeepEqual`. ### Usage Example ```ts import { strictShallowEqual } from 'fast-equals'; const a: any = ['foo']; const b: any = ['foo']; a.tag = 'v1'; b.tag = 'v1'; strictShallowEqual(a, b); // true strictShallowEqual(a, ['foo']); // false — b missing .tag ``` ``` -------------------------------- ### Interface Definitions for Custom Equality Comparator Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Defines the structure for a cache and the configuration options for creating a custom equality comparator. These interfaces are used internally by `createCustomEqual` to manage state and define comparison logic for various data types. ```typescript interface Cache { delete(key: Key): boolean; get(key: Key): Value | undefined; set(key: Key, value: any): any; } interface ComparatorConfig { areArrayBuffersEqual: EqualityComparator; areArraysEqual: EqualityComparator; areDataViewsEqual: EqualityComparator; areDatesEqual: EqualityComparator; areErrorsEqual: EqualityComparator; areFunctionsEqual: EqualityComparator; areMapsEqual: EqualityComparator; areNumbersEqual: EqualityComparator; areObjectsEqual: EqualityComparator; arePrimitiveWrappersEqual: EqualityComparator; areRegExpsEqual: EqualityComparator; areSetsEqual: EqualityComparator; areTypedArraysEqual: EqualityComparator; areUrlsEqual: EqualityComparator; getUnsupportedCustomComparator: (a: Type, b: Type, state: State, tag: string) => EqualityComparator; } ``` -------------------------------- ### Custom Equality Comparator Factory Function Signature Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Defines the signature for the `createCustomEqual` factory function, which allows for the creation of bespoke equality comparators. It accepts an options object to customize behavior like circularity handling, internal comparator creation, state management, and strictness. ```typescript function createCustomEqual(options: { circular?: boolean; createCustomConfig?: (defaultConfig: ComparatorConfig) => Partial>; createInternalComparator?: ( compare: (a: A, b: B, state: State) => boolean, ) => (a: any, b: any, indexOrKeyA: any, indexOrKeyB: any, parentA: any, parentB: any, state: State) => boolean; createState?: () => { cache?: Cache; meta?: Meta }; strict?: boolean; }): (a: A, b: B) => boolean; ``` -------------------------------- ### Adjust Line Endings for Checksum Match Source: https://github.com/planttheidea/fast-equals/blob/main/BUILD.md On Linux, you may need to adjust line endings in the build artifact to match npm release checksums. ```bash unix2dos dist/fast-equals.min.js ``` -------------------------------- ### Custom RegExp Comparator for Legacy Environments Source: https://github.com/planttheidea/fast-equals/blob/main/recipes/legacy-regexp-support.md Use this comparator when `RegExp.prototype.flags` is not available. It manually checks each flag property for equality. ```typescript import { createCustomEqual, sameValueEqual } from 'deep-Equals'; const areRegExpsEqual = (a: RegExp, b: RegExp) => a.source === b.source && a.global === b.global && a.ignoreCase === b.ignoreCase && a.multiline === b.multiline && a.unicode === b.unicode && a.sticky === b.sticky && a.lastIndex === b.lastIndex; const deepEqual = createCustomEqual({ createCustomConfig: () => ({ areRegExpsEqual }), }); const shallowEqual = createCustomEqual({ comparator: sameValueEqual, createCustomConfig: () => ({ areRegExpsEqual }), }); ``` -------------------------------- ### SameValue Equality Comparison Source: https://context7.com/planttheidea/fast-equals/llms.txt Use `sameValueEqual` as a ponyfill for `Object.is`. It treats `NaN` as equal to `NaN` but `+0` as not equal to `-0`. ```typescript import { sameValueEqual } from 'fast-equals'; sameValueEqual(NaN, NaN); // true sameValueEqual(+0, -0); // false sameValueEqual(1, 1); // true sameValueEqual('a', 'b'); // false sameValueEqual(null, null); // true sameValueEqual({}, {}); // false — referential equality only ``` -------------------------------- ### Perform Strict Equality Comparison Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Use `strictEqual` for standard strict equality comparisons (`===`). Note that NaN is not equal to NaN with this method. ```typescript import { strictEqual } from 'fast-equals'; const mainObject = { foo: NaN, bar: 'baz' }; const objectA = 'baz'; const objectB = NaN; const objectC = { foo: NaN, bar: 'baz' }; console.log(sameValueEqual(mainObject.bar, objectA)); // true console.log(sameValueEqual(mainObject.foo, objectB)); // false console.log(sameValueEqual(mainObject, objectC)); // false ``` -------------------------------- ### Create Custom Comparator for Special Objects Source: https://github.com/planttheidea/fast-equals/blob/main/recipes/special-objects.md Use `createCustomEqual` to define custom comparison logic for objects not handled by default, like Temporal.ZonedDateTime. The `getUnsupportedCustomComparator` function allows you to specify a comparator for specific `Symbol.toStringTag` values. ```typescript import { createCustomEqual } from 'fast-equals'; const areZonedDateTimesEqual = (a: unknown, b: unknown) => a instanceof Temporal.ZonedDateTime && b instanceof Temporal.ZonedDateTime && a.equals(b); const isSpecialObjectEqual = createCustomEqual({ createCustomConfig: () => ({ getUnsupportedCustomComparator(a) { if (a?.[Symbol.toStringTag] === 'Temporal.ZonedDateTime') { return areZonedDateTimesEqual; } }, }), }); ``` -------------------------------- ### strictEqual Source: https://context7.com/planttheidea/fast-equals/llms.txt A convenience wrapper around the strict equality operator (`===`). Useful as a default functional equality comparator argument. Note that `NaN !== NaN` and `+0 === -0`. ```APIDOC ## strictEqual ### Description A thin convenience wrapper around `===`. Useful as a default functional equality comparator argument. `NaN !== NaN`, `+0 === -0`. ### Method `strictEqual(value: any, other: any): boolean` ### Parameters - **value**: The first value to compare. - **other**: The second value to compare. ### Request Example ```javascript import { strictEqual } from 'fast-equals'; console.log(strictEqual(1, 1)); // true console.log(strictEqual(NaN, NaN)); // false console.log(strictEqual(+0, -0)); // true console.log(strictEqual('a', 'a')); // true console.log(strictEqual({}, {})); // false ``` ### Response - **boolean**: `true` if the values are strictly equal, `false` otherwise. ``` -------------------------------- ### Deep Equality for Maps Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Fast-equals performs deep equality comparisons for Map keys and values, ensuring that complex keys like objects and arrays are compared by their content rather than their reference. This differs from the default Map key lookup behavior which uses SameValueZero. ```javascript const mapA = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]); const mapB = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]); deepEqual(mapA, mapB); ``` -------------------------------- ### Strict Shallow Equality Comparison Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Use `strictShallowEqual` for a shallow equality comparison that includes checking non-enumerable properties, full property descriptors, non-index array properties, and non-key Map/Set properties. ```javascript const array = ['foo']; const otherArray = ['foo']; array.bar = 'baz'; otherArray.bar = 'baz'; console.log(strictDeepEqual(array, otherArray)); // true; console.log(strictDeepEqual(array, ['foo'])); // false; ``` -------------------------------- ### shallowEqual Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Performs a shallow equality comparison on two objects, returning true if their direct properties are equivalent, and false otherwise. Useful for comparing objects without recursing into nested structures. ```APIDOC ## shallowEqual ### Description Performs a shallow equality comparison on the two objects passed and returns a boolean representing the value equivalency of the objects. ### Code ```ts import { shallowEqual } from 'fast-equals'; const nestedObject = { bar: 'baz' }; const objectA = { foo: nestedObject }; const objectB = { foo: nestedObject }; const objectC = { foo: { bar: 'baz' } }; console.log(objectA === objectB); // false console.log(shallowEqual(objectA, objectB)); // true console.log(shallowEqual(objectA, objectC)); // false ``` ``` -------------------------------- ### `strictDeepEqual` Source: https://context7.com/planttheidea/fast-equals/llms.txt Performs a deep equality check with additional strictness. It considers Symbol properties, non-enumerable properties, full property descriptor shapes, non-index properties on arrays, and non-key properties on Maps/Sets. ```APIDOC ## `strictDeepEqual` ### Description Deep equality with additional strict checks beyond enumerable own keys: - Symbol properties - Non-enumerable properties - Full property descriptor shape (`configurable`, `enumerable`, `writable`) - Non-index properties on arrays - Non-key properties on `Map`/`Set` ### Usage Example ```ts import { strictDeepEqual } from 'fast-equals'; const a: any = [{ foo: 'bar' }]; const b: any = [{ foo: 'bar' }]; a.extra = 'baz'; b.extra = 'baz'; strictDeepEqual(a, b); // true — same extra property strictDeepEqual(a, [{ foo: 'bar' }]); // false — b missing .extra // Non-enumerable property check const obj1 = {}; const obj2 = {}; Object.defineProperty(obj1, 'hidden', { value: 1, enumerable: false }); Object.defineProperty(obj2, 'hidden', { value: 1, enumerable: false }); strictDeepEqual(obj1, obj2); // true Object.defineProperty(obj2, 'hidden', { value: 2, enumerable: false }); strictDeepEqual(obj1, obj2); // false ``` ``` -------------------------------- ### Strict Deep Equality Comparison Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Use `strictDeepEqual` for a deep equality comparison that includes checking symbol properties, non-enumerable properties, full property descriptors, non-index array properties, and non-key Map/Set properties. ```javascript const array = [{ foo: 'bar' }]; const otherArray = [{ foo: 'bar' }]; array.bar = 'baz'; otherArray.bar = 'baz'; console.log(strictDeepEqual(array, otherArray)); // true; console.log(strictDeepEqual(array, [{ foo: 'bar' }])); // false; ``` -------------------------------- ### Custom Equality Check for Special Objects Source: https://github.com/planttheidea/fast-equals/blob/main/recipes/explicit-property-check.md Define a custom equality function for objects with a known structure to optimize performance. This is useful when deep equality checks are a bottleneck and object shapes are predictable. ```typescript import { createCustomEqual } from 'fast-equals'; interface SpecialObject { foo: string; bar: { baz: number; }; } const areObjectsEqual = (a: SpecialObject, b: SpecialObject) => a.foo === b.foo && a.bar.baz === b.bar.baz; const isSpecialObjectEqual = createCustomEqual({ createCustomConfig: () => ({ areObjectsEqual }), }); ``` -------------------------------- ### Fast-Equals TypeScript Type Definitions Source: https://context7.com/planttheidea/fast-equals/llms.txt Imports common TypeScript type definitions used within the fast-equals library. These types help in understanding and utilizing the library's advanced features, such as custom comparators and state management. ```typescript import type { Cache, ComparatorConfig, CustomEqualCreatorOptions, EqualityComparator, InternalEqualityComparator, PrimitiveWrapper, State, TypedArray, } from 'fast-equals'; ``` -------------------------------- ### Perform SameValue Comparison Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Use `sameValueEqual` for comparisons where +0 and -0 are not equal, and NaN is equal to NaN. This function is a re-export of `Object.is` in supporting environments. ```typescript import { sameValueEqual } from 'fast-equals'; const mainObject = { foo: NaN, bar: 'baz' }; const objectA = 'baz'; const objectB = NaN; const objectC = { foo: NaN, bar: 'baz' }; console.log(sameValueEqual(mainObject.bar, objectA)); // true console.log(sameValueEqual(mainObject.foo, objectB)); // true console.log(sameValueEqual(mainObject, objectC)); // false ``` -------------------------------- ### Custom Object Comparator for Non-Standard Properties Source: https://github.com/planttheidea/fast-equals/blob/main/recipes/non-standard-properties.md Define a custom object comparator to handle objects with non-standard properties, such as those defined on the prototype or stored in WeakMaps. This is useful when default comparison logic is insufficient. ```typescript import { createCustomEqual } from 'fast-equals'; import type { EqualityComparator } from 'fast-equals'; const hiddenReferences = new WeakMap(); class HiddenProperty { hidden!: string; visible: boolean; constructor(value: string) { this.visible = true; hiddenReferences.set(this, value); } } HiddenProperty.prototype.hidden = 'foo'; function createAreObjectsEqual>( areObjectsEqual: AreObjectsEqual, ): AreObjectsEqual { return function (a, b, state) { if (!areObjectsEqual(a, b, state)) { return false; } const aInstance = a instanceof HiddenProperty; const bInstance = b instanceof HiddenProperty; if (aInstance || bInstance) { return ( aInstance && bInstance && a.hidden === 'foo' && b.hidden === 'foo' && hiddenReferences.get(a) === hiddenReferences.get(b) ); } return true; }; } const deepEqual = createCustomEqual({ createCustomConfig: ({ areObjectsEqual }) => ({ areObjectsEqual: createAreObjectsEqual(areObjectsEqual), }), }); ``` -------------------------------- ### deepEqual Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Performs a deep equality comparison on two objects, returning true if they are equivalent, and false otherwise. Handles complex nested structures and custom types. ```APIDOC ## deepEqual ### Description Performs a deep equality comparison on the two objects passed and returns a boolean representing the value equivalency of the objects. ### Code ```ts import { deepEqual } from 'fast-equals'; const objectA = { foo: { bar: 'baz' } }; const objectB = { foo: { bar: 'baz' } }; console.log(objectA === objectB); // false console.log(deepEqual(objectA, objectB)); // true ``` ### Comparing `Map`s `Map` objects support complex keys (objects, Arrays, etc.), however [the spec for key lookups in `Map` are based on `SameZeroValue`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#key_equality). If the spec were followed for comparison, the following would always be `false`: ```ts const mapA = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]); const mapB = new Map([[{ foo: 'bar' }, { baz: 'quz' }]]); deepEqual(mapA, mapB); ``` To support true deep equality of all contents, `fast-equals` will perform a deep equality comparison for key and value pairs. Therefore, the above would be `true`. ``` -------------------------------- ### Shallow Equality Comparison Source: https://context7.com/planttheidea/fast-equals/llms.txt Use `shallowEqual` for a one-level comparison. Nested object references must be identical; their contents are not checked recursively. ```typescript import { shallowEqual } from 'fast-equals'; const nested = { c: 3 }; shallowEqual({ a: 1, b: nested }, { a: 1, b: nested }); // true — same reference shallowEqual({ a: 1, b: nested }, { a: 1, b: { c: 3 } }); // false — different reference shallowEqual([1, 2, 3], [1, 2, 3]); // true — primitives match shallowEqual({ a: 1, b: 2 }, { a: 1 }); // false — different key count ``` -------------------------------- ### Shallow Equality Comparison with Circular References Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Use `circularShallowEqual` for shallow equality comparisons on objects that may contain circular references. This function is slower than `shallowEqual`. ```javascript const array = ['foo']; array.push(array); console.log(circularShallowEqual(array, ['foo', array])); // true console.log(circularShallowEqual(array, [array])); // false ``` -------------------------------- ### `strictCircularShallowEqual` Source: https://context7.com/planttheidea/fast-equals/llms.txt Combines shallow equality checking with circular reference safety and strict property descriptor checks. It's useful for comparing objects with circular structures at a shallow level while enforcing strictness on property descriptors. ```APIDOC ## `strictCircularShallowEqual` ### Description Combines `circularShallowEqual` with strict property descriptor checking. ### Usage Example ```ts import { strictCircularShallowEqual } from 'fast-equals'; const a: any = ['foo']; const b: any = ['foo']; a.push(a); // circular b.push(b); // circular a.label = 'same'; b.label = 'same'; strictCircularShallowEqual(a, b); // true strictCircularShallowEqual(a, ['foo', a]); // false — b missing .label ``` ``` -------------------------------- ### `circularShallowEqual` Source: https://context7.com/planttheidea/fast-equals/llms.txt Performs a shallow equality check that is safe against circular references. It compares the top-level properties of objects or elements of arrays, while also handling circular structures. ```APIDOC ## `circularShallowEqual` ### Description Identical to `shallowEqual` but safe against circular references. ### Usage Example ```ts import { circularShallowEqual } from 'fast-equals'; const arr: any[] = ['foo']; arr.push(arr); // arr[1] === arr (circular) circularShallowEqual(arr, ['foo', arr]); // true circularShallowEqual(arr, [arr]); // false — first element differs ``` ``` -------------------------------- ### Deep Equality Comparison with Circular References Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Use `circularDeepEqual` when you need to perform a deep equality comparison on objects that may contain circular references. This function is slower than `deepEqual`. ```javascript function Circular(value) { this.me = { deeply: { nested: { reference: this, }, }, value, }; } console.log(circularDeepEqual(new Circular('foo'), new Circular('foo'))); // true console.log(circularDeepEqual(new Circular('foo'), new Circular('bar'))); // false ``` -------------------------------- ### Strict Circular Deep Equality Comparison Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Compares objects for deep equality, including Symbol properties, non-enumerable properties, full property descriptors, non-index array properties, and non-key Map/Set properties. Use when a thorough, strict comparison of potentially circular objects is needed. ```typescript function Circular(value) { this.me = { deeply: { nested: { reference: this, }, }, value, }; } const first = new Circular('foo'); Object.defineProperty(first, 'bar', { enumerable: false, value: 'baz', }); const second = new Circular('foo'); Object.defineProperty(second, 'bar', { enumerable: false, value: 'baz', }); console.log(circularDeepEqual(first, second)); // true console.log(circularDeepEqual(first, new Circular('foo'))); // false ``` -------------------------------- ### `circularDeepEqual` Source: https://context7.com/planttheidea/fast-equals/llms.txt Performs a deep equality check that is safe against circular references. It uses a WeakMap to track visited objects, preventing infinite recursion. This function is recommended when circular structures are expected, though it may be slightly slower than `deepEqual`. ```APIDOC ## `circularDeepEqual` ### Description Identical to `deepEqual` but safe against objects with circular references. Uses a `WeakMap` cache internally to track already-visited nodes and avoid infinite recursion. Slightly slower than `deepEqual`; only use when circular structures are expected. ### Usage Example ```ts import { circularDeepEqual } from 'fast-equals'; function Circular(value: string) { this.me = { deeply: { nested: { reference: this } }, value }; } circularDeepEqual(new Circular('foo'), new Circular('foo')); // true circularDeepEqual(new Circular('foo'), new Circular('bar')); // false // Circular array const arr: any[] = ['foo']; arr.push(arr); // arr[1] === arr circularDeepEqual(arr, ['foo', arr]); // true ``` ``` -------------------------------- ### Strict Circular Shallow Equality Comparison Source: https://github.com/planttheidea/fast-equals/blob/main/README.md Compares objects for shallow equality, including non-enumerable properties, full property descriptors, non-index array properties, and non-key Map/Set properties. Use for a strict, but not deeply recursive, comparison of potentially circular objects. ```typescript const array = ['foo']; const otherArray = ['foo']; array.push(array); otherArray.push(otherArray); array.bar = 'baz'; otherArray.bar = 'baz'; console.log(circularShallowEqual(array, otherArray)); // true console.log(circularShallowEqual(array, ['foo', array])); // false ```