Starting in version 4.x.x, fast-equals requires WeakMap to be available in the environment for circular equality checks. If you are targeting legacy environments (like IE11) where WeakMap is unavailable and polyfilling is not an option, you can implement a custom comparator using createCustomEqual.
To do this, you must provide a createState function that returns a custom cache implementation adhering to the Cache contract (implementing get, set, and delete methods). This allows you to perform circular equality checks using a manual array-based or alternative cache mechanism instead of relying on the global WeakMap.
import { createCustomEqual, sameValueEqual } from 'fast-equals';
import type { Cache } from 'fast-equals';
// 1. Implement a custom cache that follows the Cache contract
function getCache(): Cache<any, any> {
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;
},
};
}
// 2. Use createCustomEqual to inject the custom cache via createState
const circularDeepEqual = createCustomEqual<Cache>({
circular: true,
createState: () => ({
cache: getCache(),
}),
});
// Or with a specific comparator like sameValueEqual
const circularShallowEqual = createCustomEqual<Cache>({
circular: true,
comparator: sameValueEqual,
createState: () => ({
cache: getCache(),
}),
});