UNPKG

typedash

Version:

modern, type-safe collection of utility functions

1 lines 30 kB
{"version":3,"sources":["../../src/functions/zip/zip.ts","../../src/functions/isEqual/_internal/array/areArraysEqual.ts","../../src/functions/isEqual/_internal/createIsCircularTypeEqualityComparator.ts","../../src/functions/isEqual/_internal/date/areDatesEqual.ts","../../src/functions/isEqual/_internal/date/dateTag.ts","../../src/functions/isEqual/_internal/map/areMapsEqual.ts","../../src/functions/isEqual/_internal/react/reactOwnerPropertyName.ts","../../src/functions/isEqual/_internal/object/getObjectProperties.ts","../../src/functions/isEqual/_internal/object/areObjectsEqual.ts","../../src/functions/isEqual/_internal/primitiveWrappers/arePrimitiveWrappersEqual.ts","../../src/functions/isEqual/_internal/regExp/areRegExpsEqual.ts","../../src/functions/isEqual/_internal/regExp/regExpTag.ts","../../src/functions/isEqual/_internal/set/areSetsEqual.ts","../../src/functions/isEqual/_internal/set/setTag.ts","../../src/functions/isEqual/_internal/typedArray/areTypedArraysEqual.ts","../../src/functions/isEqual/_internal/typedArray/isTypedArray.ts","../../src/functions/isEqual/_internal/comparator.ts","../../src/functions/isArray/isArray.ts","../../src/functions/isEqual/_internal/createEqualityComparator.ts","../../src/functions/isEqual/isEqual.ts"],"names":["isEqual","areArraysEqual","areDatesEqual","areMapsEqual","areObjectsEqual","arePrimitiveWrappersEqual","areRegExpsEqual","areSetsEqual","areTypedArraysEqual"],"mappings":"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","sourcesContent":["import type { TypedArray } from 'type-fest';\n\n/**\n * Zips two arrays together into an array of tuples.\n * @param first The first array to zip.\n * @param second The second array to zip.\n * @returns An array of tuples containing the zipped values.\n */\nexport function zip<T, U>(\n first: readonly T[],\n second: readonly U[]\n): Array<[T, U]>;\n/**\n * Zips two typed arrays together into an array of tuples.\n * @param first The first array to zip.\n * @param second The second array to zip.\n * @returns An array of tuples containing the zipped values.\n */\nexport function zip<T extends TypedArray, U extends TypedArray>(\n first: T,\n second: U\n): Array<[T[number], U[number]]>;\n/**\n * Implementation for all overloads.\n * @param first The first array to zip.\n * @param second The second array to zip.\n * @returns An array of tuples containing the zipped values.\n */\nexport function zip<\n T extends readonly unknown[] | TypedArray,\n U extends readonly unknown[] | TypedArray,\n>(first: T, second: U) {\n const result: Array<[T[number], U[number]]> = [];\n\n for (let index = 0; index < Math.min(first.length, second.length); index++) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- we're getting the min length first\n result.push([first[index]!, second[index]!]);\n }\n\n return result;\n}\n","import { zip } from '../../../zip';\nimport type { Context } from '../types';\n\n/**\n * Whether the arrays are equal in value.\n * @param array1 The first array.\n * @param array2 The second array.\n * @param context The context object.\n * @returns true if the two arrays are equal, false otherwise.\n */\nexport function areArraysEqual(\n array1: readonly unknown[],\n array2: readonly unknown[],\n context: Context\n) {\n if (array1.length !== array2.length) {\n return false;\n }\n\n for (const [index, [element1, element2]] of zip(array1, array2).entries()) {\n if (\n !context.equals(element1, element2, index, index, array1, array2, context)\n ) {\n return false;\n }\n }\n\n return true;\n}\n","import { Context, TypeEqualityComparator } from './types';\n\n/**\n * Wrap the provided `areItemsEqual` method to manage the circular state, allowing\n * for circular references to be safely included in the comparison without creating\n * stack overflows.\n * @param areItemsEqual The comparator to wrap.\n * @returns A comparator that can handle circular references.\n */\nexport function createIsCircularTypeEqualityComparator<T>(\n areItemsEqual: TypeEqualityComparator<T>\n) {\n return function isCircular(a: T, b: T, context: Context) {\n if (!a || !b || typeof a !== 'object' || typeof b !== 'object') {\n return areItemsEqual(a, b, context);\n }\n\n const { cache } = context;\n\n const cachedA = cache.get(a);\n const cachedB = cache.get(b);\n\n if (cachedA && cachedB) {\n return cachedA === b && cachedB === a;\n }\n\n cache.set(a, b);\n cache.set(b, a);\n\n const result = areItemsEqual(a, b, context);\n\n cache.delete(a);\n cache.delete(b);\n\n return result;\n };\n}\n","/**\n * Whether the dates passed are equal in value.\n * @param value1 The first date.\n * @param value2 The second date.\n * @returns true if the two dates are equal, false otherwise.\n */\nexport function areDatesEqual(value1: Date, value2: Date): boolean {\n return Object.is(value1.getTime(), value2.getTime());\n}\n","export const DATE_TAG = '[object Date]';\n","import { Context } from '../types';\n\n/**\n * Whether the `Map`s are equal in value.\n * @param value1 The first `Map`.\n * @param value2 The second `Map`.\n * @param context The context object.\n * @returns true if the two `Map`s are equal, false otherwise.\n */\nexport function areMapsEqual(\n value1: ReadonlyMap<unknown, unknown>,\n value2: ReadonlyMap<unknown, unknown>,\n context: Context\n): boolean {\n if (value1.size !== value2.size) {\n return false;\n }\n\n const matchedIndices: Record<number, true> = {};\n\n let index = 0;\n\n for (const [aKey, aValue] of value1) {\n let hasMatch = false;\n let matchIndex = 0;\n\n for (const [bKey, bValue] of value2) {\n if (\n !hasMatch &&\n !matchedIndices[matchIndex] &&\n // eslint-disable-next-line no-cond-assign\n (hasMatch =\n context.equals(\n aKey,\n bKey,\n index,\n matchIndex,\n value1,\n value2,\n context\n ) &&\n context.equals(aValue, bValue, aKey, bKey, value1, value2, context))\n ) {\n matchedIndices[matchIndex] = true;\n }\n\n matchIndex++;\n }\n\n if (!hasMatch) {\n return false;\n }\n\n index++;\n }\n\n return true;\n}\n","/**\n * React-specific internal property that is used to track the component that created another component.\n * Provides us with simple circular reference detection and handling.\n */\nexport const REACT_OWNER_PROPERTY_NAME = '_owner';\n","import { Dictionary } from './Dictionary';\n\n/**\n * Get the properties to strictly examine, which include both own properties that are\n * not enumerable and symbol properties.\n * @param object The object to get the properties for.\n * @returns The properties to strictly examine.\n */\nexport function getObjectProperties(\n object: Dictionary\n): Array<string | symbol> {\n return [\n ...Object.getOwnPropertyNames(object),\n ...Object.getOwnPropertySymbols(object),\n ];\n}\n","import { REACT_OWNER_PROPERTY_NAME } from '../react';\nimport { Context } from '../types/types';\n\nimport { Dictionary } from './Dictionary';\nimport { getObjectProperties } from './getObjectProperties';\n\n/**\n * Whether the objects are equal in value with strict property checking.\n * @param value1 The first object.\n * @param value2 The second object.\n * @param context The context object.\n * @returns true if the two objects are equal, false otherwise.\n */\nexport function areObjectsEqual(\n value1: Dictionary,\n value2: Dictionary,\n context: Context\n): boolean {\n const properties = getObjectProperties(value1);\n\n if (getObjectProperties(value2).length !== properties.length) {\n return false;\n }\n\n for (const property of properties) {\n if (\n property === REACT_OWNER_PROPERTY_NAME &&\n (value1.$$typeof || value2.$$typeof) &&\n value1.$$typeof !== value2.$$typeof\n ) {\n return false;\n }\n\n if (!Object.hasOwn(value2, property)) {\n return false;\n }\n\n if (\n !context.equals(\n value1[property],\n value2[property],\n property,\n property,\n value1,\n value2,\n context\n )\n ) {\n return false;\n }\n }\n\n return true;\n}\n","/**\n * Whether the primitive wrappers passed are equal in value.\n * @param value1 The first primitive wrapper.\n * @param value2 The second primitive wrapper.\n * @returns true if the two primitive wrappers are equal, false otherwise.\n */\nexport function arePrimitiveWrappersEqual(\n value1: PrimitiveWrapper,\n value2: PrimitiveWrapper\n): boolean {\n return Object.is(value1.valueOf(), value2.valueOf());\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types -- we explicitly check for primitive wrapper types\nexport type PrimitiveWrapper = Boolean | Number | String;\n","/**\n * Whether the regexps passed are equal in value.\n * @param value1 The first regexp.\n * @param value2 The second regexp.\n * @returns true if the two regexps are equal, false otherwise.\n */\nexport function areRegExpsEqual(value1: RegExp, value2: RegExp): boolean {\n return value1.source === value2.source && value1.flags === value2.flags;\n}\n","export const REG_EXP_TAG = '[object RegExp]';\n","import { Context } from '../types';\n\n/**\n * Whether the `Set`s are equal in value.\n * @param set1 The first `Set`.\n * @param set2 The second `Set`.\n * @param context The context object.\n * @returns true if the two `Set`s are equal, false otherwise.\n */\nexport function areSetsEqual(\n set1: ReadonlySet<unknown>,\n set2: ReadonlySet<unknown>,\n context: Context\n): boolean {\n if (set1.size !== set2.size) {\n return false;\n }\n\n const matchedIndices: Record<number, true> = {};\n\n for (const element1 of set1) {\n let hasMatch = false;\n let matchIndex = 0;\n\n for (const element2 of set2) {\n if (\n !hasMatch &&\n !matchedIndices[matchIndex] &&\n // eslint-disable-next-line no-cond-assign\n (hasMatch = context.equals(\n element1,\n element2,\n element1,\n element2,\n set1,\n set2,\n context\n ))\n ) {\n matchedIndices[matchIndex] = true;\n }\n\n matchIndex++;\n }\n\n if (!hasMatch) {\n return false;\n }\n }\n\n return true;\n}\n","export const SET_TAG = '[object Set]';\n","import type { TypedArray } from 'type-fest';\n\nimport { zip } from '../../../zip';\n\n/**\n * Whether the TypedArray instances are equal in value.\n * @param array1 The first TypedArray instance.\n * @param array2 The second TypedArray instance.\n * @returns true if the two TypedArray instances are equal, false otherwise.\n */\nexport function areTypedArraysEqual(array1: TypedArray, array2: TypedArray) {\n if (array1.length !== array2.length) {\n return false;\n }\n\n for (const [element1, element2] of zip(array1, array2)) {\n if (element1 !== element2) {\n return false;\n }\n }\n\n return true;\n}\n","export const isTypedArray =\n typeof ArrayBuffer === 'function' && ArrayBuffer.isView\n ? ArrayBuffer.isView\n : null;\n","/* eslint-disable jsdoc/require-returns */\n/* eslint-disable jsdoc/require-param */\n\nimport { areArraysEqual } from './array';\nimport { createIsCircularTypeEqualityComparator } from './createIsCircularTypeEqualityComparator';\nimport { areDatesEqual } from './date';\nimport { areMapsEqual } from './map';\nimport { areObjectsEqual } from './object';\nimport { arePrimitiveWrappersEqual } from './primitiveWrappers';\nimport { areRegExpsEqual } from './regExp';\nimport { areSetsEqual } from './set';\nimport { areTypedArraysEqual } from './typedArray';\nimport type {\n ComparatorConfig,\n Context,\n EqualityComparator,\n InternalEqualityComparator,\n} from './types';\n\nexport const ARGUMENTS_TAG = '[object Arguments]';\nexport const BOOLEAN_TAG = '[object Boolean]';\nexport const MAP_TAG = '[object Map]';\nexport const NUMBER_TAG = '[object Number]';\nexport const OBJECT_TAG = '[object Object]';\nexport const STRING_TAG = '[object String]';\n\nexport const getTag = Object.prototype.toString.call.bind(\n Object.prototype.toString\n) as (a: object) => string;\n\ninterface CreateIsEqualOptions {\n comparator: EqualityComparator;\n equals: InternalEqualityComparator;\n}\n\n/**\n * Create the configuration object used for building comparators.\n */\nexport function createEqualityComparatorConfig(): ComparatorConfig {\n return {\n areDatesEqual,\n areRegExpsEqual,\n arePrimitiveWrappersEqual,\n areArraysEqual: createIsCircularTypeEqualityComparator(areArraysEqual),\n areMapsEqual: createIsCircularTypeEqualityComparator(areMapsEqual),\n areObjectsEqual: createIsCircularTypeEqualityComparator(areObjectsEqual),\n areSetsEqual: createIsCircularTypeEqualityComparator(areSetsEqual),\n areTypedArraysEqual,\n };\n}\n\n/**\n * Default equality comparator pass-through, used as the standard `isEqual` creator for\n * use inside the built comparator.\n */\nexport function createInternalEqualityComparator(\n compare: EqualityComparator\n): InternalEqualityComparator {\n return function internalEqualityComparator(\n value1: unknown,\n value2: unknown,\n _indexOrKeyA: unknown,\n _indexOrKeyB: unknown,\n _parentA: unknown,\n _parentB: unknown,\n context: Context\n ) {\n return compare(value1, value2, context);\n };\n}\n\n/**\n * Create the `isEqual` function used by the consuming application.\n */\nexport function createIsEqual({ comparator, equals }: CreateIsEqualOptions) {\n return function isEqual<T1, T2>(value1: T1, value2: T2): boolean {\n return comparator(value1, value2, {\n cache: new WeakMap(),\n equals,\n });\n };\n}\n","import { Many, Maybe } from '../../types';\n\n// eslint-disable-next-line prefer-destructuring\nexport const isArray: IsArray = Array.isArray;\n\ninterface IsArray {\n /**\n * The same as `Array.isArray` but with a better type guard.\n * @param value The value to check.\n * @returns `true` if the value is an array, `false` otherwise.\n * @example\n * ```ts\n * isArray([1, 2, 3]) // true\n * isArray('foo') // false\n * ```\n */\n <T>(value: Maybe<Array<ArrayElement<T>>>): value is NonNullable<typeof value>;\n /**\n * The same as `Array.isArray` but with a better type guard.\n * @param value The value to check.\n * @returns `true` if the value is an array, `false` otherwise.\n * @example\n * ```ts\n * isArray([1, 2, 3]) // true\n * isArray('foo') // false\n * ```\n */\n <T>(\n value: Maybe<ReadonlyArray<ArrayElement<T>>>\n ): value is NonNullable<typeof value>;\n\n /**\n * The same as `Array.isArray` but with a better type guard.\n * @param value The value to check.\n * @returns `true` if the value is an array, `false` otherwise.\n * @example\n * ```ts\n * isArray([1, 2, 3]) // true\n * isArray('foo') // false\n * ```\n */\n <T>(value: Maybe<Many<T>>): value is NonNullable<readonly T[]>;\n /**\n * The same as `Array.isArray` but with a better type guard.\n * @param value The value to check.\n * @returns `true` if the value is an array, `false` otherwise.\n * @example\n * ```ts\n * isArray([1, 2, 3]) // true\n * isArray('foo') // false\n * ```\n */\n <T>(value: unknown): value is readonly T[];\n}\n\ntype ArrayElement<T> = T extends ReadonlyArray<infer U> ? U : never;\n","/* eslint-disable @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access -- this entire file is basically unsafe at the type-level, but we check the types at runtime\n and act accordingly. */\n\nimport type { TypedArray } from 'type-fest';\n\nimport { isArray } from '../../isArray';\n\nimport {\n ARGUMENTS_TAG,\n BOOLEAN_TAG,\n getTag,\n MAP_TAG,\n NUMBER_TAG,\n OBJECT_TAG,\n STRING_TAG,\n} from './comparator';\nimport { DATE_TAG } from './date';\nimport { REG_EXP_TAG } from './regExp';\nimport { SET_TAG } from './set';\nimport { isTypedArray } from './typedArray';\nimport type { ComparatorConfig, Context, EqualityComparator } from './types';\n\n/**\n * Create a comparator method based on the type-specific equality comparators passed.\n * @param root0 The configuration object.\n * @param root0.areArraysEqual The array equality comparator.\n * @param root0.areDatesEqual The date equality comparator.\n * @param root0.areMapsEqual The map equality comparator.\n * @param root0.areObjectsEqual The object equality comparator.\n * @param root0.arePrimitiveWrappersEqual The primitive wrapper equality comparator.\n * @param root0.areRegExpsEqual The regular expression equality comparator.\n * @param root0.areSetsEqual The set equality comparator.\n * @param root0.areTypedArraysEqual The typed array equality comparator.\n * @returns The comparator method.\n */\nexport function createEqualityComparator({\n areArraysEqual,\n areDatesEqual,\n areMapsEqual,\n areObjectsEqual,\n arePrimitiveWrappersEqual,\n areRegExpsEqual,\n areSetsEqual,\n areTypedArraysEqual,\n}: ComparatorConfig): EqualityComparator {\n /**\n * compare the value of the two objects and return true if they are equivalent in values\n * @param value1 the first value to compare\n * @param value2 the second value to compare\n * @param context the context object\n * @returns true if the two values are equivalent in values\n */\n return function comparator(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value1: any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n value2: any,\n context: Context\n ): boolean {\n // If the items are strictly equal, no need to do a value comparison.\n if (Object.is(value1, value2) || value1 === value2) {\n return true;\n }\n\n // Checks are listed in order of commonality of use-case:\n // 1. Common complex object types (plain object, array)\n // 2. Common data values (date, regexp)\n // 3. Less-common complex object types (map, set)\n // 4. Less-common data values (promise, primitive wrappers)\n // Inherently this is both subjective and assumptive, however\n // when reviewing comparable libraries in the wild this order\n // appears to be generally consistent.\n // Constructors should match, otherwise there is potential for false positives\n // between class and subclass or custom object and POJO.\n if (value1?.constructor !== value2?.constructor) {\n return false;\n }\n\n // `isPlainObject` only checks against the object's own realm. Cross-realm\n // comparisons are rare, and will be handled in the ultimate fallback, so\n // we can avoid capturing the string tag.\n if (value1.constructor === Object) {\n return areObjectsEqual(value1, value2, context);\n }\n\n // `isArray()` works on subclasses and is cross-realm, so we can avoid capturing\n // the string tag or doing an `instanceof` check.\n if (isArray(value1)) {\n return areArraysEqual(value1, value2, context);\n }\n\n // `isTypedArray()` works on all possible TypedArray classes, so we can avoid\n // capturing the string tag or comparing against all possible constructors.\n if (isTypedArray?.(value1)) {\n return areTypedArraysEqual(value1 as TypedArray, value2, context);\n }\n\n // Try to fast-path equality checks for other complex object types in the\n // same realm to avoid capturing the string tag. Strict equality is used\n // instead of `instanceof` because it is more performant for the common\n // use-case. If someone is subclassing a native class, it will be handled\n // with the string tag comparison.\n if (value1.constructor === Date) {\n return areDatesEqual(value1, value2, context);\n }\n\n if (value1.constructor === RegExp) {\n return areRegExpsEqual(value1, value2, context);\n }\n\n if (value1.constructor === Map) {\n return areMapsEqual(value1, value2, context);\n }\n\n if (value1.constructor === Set) {\n return areSetsEqual(value1, value2, context);\n }\n\n // Since this is a custom object, capture the string tag to determine its type.\n const tag = getTag(value1);\n switch (tag) {\n case DATE_TAG: {\n return areDatesEqual(value1, value2, context);\n }\n case REG_EXP_TAG: {\n return areRegExpsEqual(value1, value2, context);\n }\n case MAP_TAG: {\n return areMapsEqual(value1, value2, context);\n }\n case SET_TAG: {\n return areSetsEqual(value1, value2, context);\n }\n case OBJECT_TAG: {\n // The exception for value comparison is custom `Promise`-like class instances. These should\n // be treated the same as standard `Promise` objects, which means strict equality, and if\n // it reaches this point then that strict equality comparison has already failed.\n return (\n // eslint-disable-next-line unicorn/consistent-destructuring\n // eslint-disable-next-line unicorn/consistent-destructuring\n typeof value1.then !== 'function' &&\n typeof value2.then !== 'function' &&\n areObjectsEqual(value1, value2, context)\n );\n }\n // If an arguments tag, it should be treated as a standard object.\n case ARGUMENTS_TAG: {\n return areObjectsEqual(value1, value2, context);\n }\n // As the penultimate fallback, check if the values passed are primitive wrappers. This\n // is very rare in modern JS, which is why it is deprioritized compared to all other object\n // types.\n case BOOLEAN_TAG:\n case NUMBER_TAG:\n case STRING_TAG: {\n return arePrimitiveWrappersEqual(value1, value2, context);\n }\n // If not matching any tags that require a specific type of comparison, then we hard-code false because\n // the only thing remaining is strict equality, which has already been compared. This is for a few reasons:\n // - Certain types that cannot be introspected (e.g., `WeakMap`). For these types, this is the only\n // comparison that can be made.\n // - For types that can be introspected, but rarely have requirements to be compared\n // (`ArrayBuffer`, `DataView`, etc.), the cost is avoided to prioritize the common\n // use-cases (may be included in a future release, if requested enough).\n // - For types that can be introspected but do not have an objective definition of what\n // equality is (`Error`, etc.), the subjective decision is to be conservative and strictly compare.\n // In all cases, these decisions should be reevaluated based on changes to the language and\n // common development practices.\n default: {\n return false;\n }\n }\n };\n}\n","/**\n * Slimmed down version of https://github.com/planttheidea/fast-equals\n * Without all the configuration options, and with a few tweaks to make it more readable (though a bit less performant)\n */\n\nimport {\n createEqualityComparatorConfig,\n createInternalEqualityComparator,\n createIsEqual,\n} from './_internal/comparator';\nimport { createEqualityComparator } from './_internal/createEqualityComparator';\n\n/**\n * Compare two values to determine if they are deeply equivalent by value.\n * @param value1 The first value to compare.\n * @param value2 The second value to compare.\n * @returns `true` if the two values are equivalent, `false` otherwise.\n * @example\n * ```ts\n * isEqual(1, 1); // true\n * isEqual(1, '1'); // false\n * isEqual({ a: 1 }, { a: 1 }); // true\n * isEqual({ a: 1 }, { a: 2 }); // false\n * isEqual(new Date('2020-01-01'), new Date('2020-01-01')); // true\n * isEqual(new Set([1, 2, 3]), new Set([3, 2, 1])); // true\n */\nexport const isEqual = createCustomEqual();\n\n/**\n * Create a custom equality comparison method.\n *\n * This can be done to create very targeted comparisons in extreme hot-path scenarios\n * where the standard methods are not performant enough, but can also be used to provide\n * support for legacy environments that do not support expected features like\n * `RegExp.prototype.flags` out of the box.\n * @returns A function that can be used to compare values.\n */\nfunction createCustomEqual() {\n const config = createEqualityComparatorConfig();\n const comparator = createEqualityComparator(config);\n const equals = createInternalEqualityComparator(comparator);\n\n return createIsEqual({ comparator, equals });\n}\n"]}