Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix type issues with additional strict options #82

Merged
merged 12 commits into from
Jun 5, 2022
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# fast-equals CHANGELOG

## 4.0.1

- [#81](https://github.com/planttheidea/fast-equals/issues/81) - Fix typing issues related to importing in `index.d.ts` file

## 4.0.0

### Breaking Changes
Expand Down
4 changes: 2 additions & 2 deletions DEV_ONLY/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
shallowEqual,
} from '../src';

import type { BaseCircularMeta } from '../src';
import type { BaseCircularMeta } from '../index.d';

document.body.style.backgroundColor = '#1d1d1d';
document.body.style.color = '#d5d5d5';
Expand Down Expand Up @@ -382,7 +382,7 @@ console.group('targeted custom');

const isDeepEqualOrFooMatchesMeta = createCustomEqual<'bar'>(() => ({
createIsNestedEqual:
(deepEqual) => (a, b, keyA, keyB, parentA, parentB, meta) =>
(deepEqual) => (a, b, _keyA, _keyB, _parentA, _parentB, meta) =>
a === meta || b === meta || deepEqual(a, b, meta),
}));

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<img src="https://img.shields.io/badge/coverage-100%25-brightgreen.svg"/>
<img src="https://img.shields.io/badge/license-MIT-blue.svg"/>

Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed. It has no dependencies, and is ~1.26kB when minified and gzipped.
Perform [blazing fast](#benchmarks) equality comparisons (either deep or shallow) on two objects passed. It has no dependencies, and is ~1.27kB when minified and gzipped.

Unlike most equality validation libraries, the following types are handled out-of-the-box:

Expand Down
2 changes: 1 addition & 1 deletion __tests__/comparator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { areRegExpsEqual } from '../src/regexps';
import { areSetsEqual, areSetsEqualCircular } from '../src/sets';
import { createDefaultIsNestedEqual, sameValueZeroEqual } from '../src/utils';

import type { EqualityComparatorCreator } from '../src/utils';
import type { EqualityComparatorCreator } from '../index.d';

const STANDARD_COMPARATOR_OPTIONS = {
areArraysEqual,
Expand Down
11 changes: 5 additions & 6 deletions __tests__/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// @ts-expect-error - Types do not exist for `testSuites`
import testSuites from './__helpers__/testSuites';

import {
circularDeepEqual,
circularShallowEqual,
Expand All @@ -9,7 +8,9 @@ import {
deepEqual,
sameValueZeroEqual,
shallowEqual,
} from '../src/index';
} from '../src';

import type { BaseCircularMeta } from '../index.d';

describe('exports', () => {
[
Expand Down Expand Up @@ -145,9 +146,7 @@ describe('circularShallowEqual', () => {
});

describe('createCustomEqual', () => {
type FakeWeakMap = Pick<WeakMap<any, any>, 'delete' | 'get' | 'set'>;

function getFakeWeakMap(): FakeWeakMap {
function getFakeWeakMap(): BaseCircularMeta {
const entries: [object, object][] = [];

return {
Expand Down Expand Up @@ -197,7 +196,7 @@ describe('createCustomEqual', () => {
);
}

const customDeepEqualComparator = createCustomCircularEqual<FakeWeakMap>(
const customDeepEqualComparator = createCustomCircularEqual<BaseCircularMeta>(
() => ({
areRegExpsEqual: areRegExpsEqualNoFlagsSupport,
}),
Expand Down
7 changes: 4 additions & 3 deletions __tests__/recipes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import {
createCustomEqual,
sameValueZeroEqual,
} from '../src/index';

import type {
BaseCircularMeta,
EqualityComparatorCreator,
TypeEqualityComparator,
} from '../src/index';
} from '../index.d';

describe('recipes', () => {
describe('createCustomEqual', () => {
Expand Down Expand Up @@ -61,7 +62,7 @@ describe('recipes', () => {
return a.foo === b.foo && a.bar.baz === b.bar.baz;
};

const spy = jest.fn(areObjectsEqual);
const spy = jest.fn(areObjectsEqual) as typeof areObjectsEqual;

const isSpecialObjectEqual = createCustomEqual(() => ({
areObjectsEqual: spy,
Expand All @@ -85,7 +86,7 @@ describe('recipes', () => {
const mutableState: MutableState = { state: 'baz' };

const createIsNestedEqual: EqualityComparatorCreator<MutableState> =
(deepEqual) => (a, b, keyA, keyB, parentA, parentB, meta) =>
(deepEqual) => (a, b, _keyA, _keyB, _parentA, _parentB, meta) =>
deepEqual(a, b, meta) || a === meta.state || b === meta.state;

const deepEqual = createCustomEqual(() => ({ createIsNestedEqual }));
Expand Down
43 changes: 26 additions & 17 deletions __tests__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,31 +47,40 @@ describe('isPromiseLike', () => {
});

describe('isSameValueZero', () => {
Object.keys(primitiveValues).forEach((key: keyof typeof primitiveValues) => {
Object.keys(primitiveValues).forEach((key) => {
it(`should have ${key} be equal by SameValueZero`, () => {
expect(sameValueZeroEqual(primitiveValues[key], mainValues[key])).toBe(
true,
);
expect(
sameValueZeroEqual(
primitiveValues[key as keyof typeof primitiveValues],
mainValues[key as keyof typeof primitiveValues],
),
).toBe(true);
});
});

Object.keys(mainValues).forEach((key: keyof typeof mainValues) => {
Object.keys(mainValues).forEach((key) => {
if (!Object.prototype.hasOwnProperty.call(primitiveValues, key)) {
it(`should have ${key} be equal by SameValueZero`, () => {
expect(sameValueZeroEqual(mainValues[key], mainValues[key])).toBe(true);
expect(
sameValueZeroEqual(
mainValues[key as keyof typeof mainValues],
mainValues[key as keyof typeof mainValues],
),
).toBe(true);
});
}
});

Object.keys(alternativeValues).forEach(
(key: keyof typeof alternativeValues) => {
if (Object.prototype.hasOwnProperty.call(mainValues, key)) {
it(`should have ${key} not be equal by SameValueZero`, () => {
expect(
sameValueZeroEqual(alternativeValues[key], mainValues[key]),
).toBe(false);
});
}
},
);
Object.keys(alternativeValues).forEach((key) => {
if (Object.prototype.hasOwnProperty.call(mainValues, key)) {
it(`should have ${key} not be equal by SameValueZero`, () => {
expect(
sameValueZeroEqual(
alternativeValues[key as keyof typeof alternativeValues],
mainValues[key as keyof typeof alternativeValues],
),
).toBe(false);
});
}
});
});
85 changes: 58 additions & 27 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,58 @@
import type {
circularDeepEqual as CircularDeepEqual,
circularShallowEqual as CircularShallowEqual,
createCustomEqual as CreateCustomEqual,
createCustomCircularEqual as CreateCustomCircularEqual,
deepEqual as DeepEqual,
shallowEqual as ShallowEqual,
sameValueZeroEqual as SameValueZeroEqual,
} from './src/index';

export type { BaseCircularMeta, GetComparatorOptions } from './src/index';
export type { CreateComparatorCreatorOptions } from './src/comparator';
export type {
EqualityComparator,
EqualityComparatorCreator,
InternalEqualityComparator,
NativeEqualityComparator,
TypeEqualityComparator,
} from './src/utils';

export const circularDeepEqual: typeof CircularDeepEqual;
export const circularShallowEqual: typeof CircularShallowEqual;
export const createCustomEqual: typeof CreateCustomEqual;
export const createCustomCircularEqual: typeof CreateCustomCircularEqual;
export const deepEqual: typeof DeepEqual;
export const shallowEqual: typeof ShallowEqual;
export const sameValueZeroEqual: typeof SameValueZeroEqual;
export interface BaseCircularMeta
extends Pick<WeakMap<any, any>, 'delete' | 'get'> {
set(key: object, value: any): any;
}

export interface CreateComparatorCreatorOptions<Meta> {
areArraysEqual: TypeEqualityComparator<any, Meta>;
areDatesEqual: TypeEqualityComparator<any, Meta>;
areMapsEqual: TypeEqualityComparator<any, Meta>;
areObjectsEqual: TypeEqualityComparator<any, Meta>;
areRegExpsEqual: TypeEqualityComparator<any, Meta>;
areSetsEqual: TypeEqualityComparator<any, Meta>;
createIsNestedEqual: EqualityComparatorCreator<Meta>;
}

export type GetComparatorOptions<Meta> = (
defaultOptions: CreateComparatorCreatorOptions<Meta>,
) => Partial<CreateComparatorCreatorOptions<Meta>>;

export type InternalEqualityComparator<Meta> = (
a: any,
b: any,
indexOrKeyA: any,
indexOrKeyB: any,
parentA: any,
parentB: any,
meta: Meta,
) => boolean;

export type EqualityComparator<Meta> = Meta extends undefined
? <A, B>(a: A, b: B, meta?: Meta) => boolean
: <A, B>(a: A, b: B, meta: Meta) => boolean;

export type EqualityComparatorCreator<Meta> = (
fn: EqualityComparator<Meta>,
) => InternalEqualityComparator<Meta>;

export type NativeEqualityComparator = <A, B>(a: A, b: B) => boolean;

export type TypeEqualityComparator<Type, Meta> = (
a: Type,
b: Type,
isEqual: InternalEqualityComparator<Meta>,
meta: Meta,
) => boolean;

export function circularDeepEqual<A, B>(a: A, b: B): boolean;
export function circularShallowEqual<A, B>(a: A, b: B): boolean;
export function deepEqual<A, B>(a: A, b: B): boolean;
export function shallowEqual<A, B>(a: A, b: B): boolean;
export function sameValueZeroEqual<A, B>(a: A, b: B): boolean;

export function createCustomEqual<Meta = undefined>(
getComparatorOptions: GetComparatorOptions<Meta>,
): EqualityComparator<Meta>;
export function createCustomEqual<Meta = WeakMap<any, any>>(
getComparatorOptions: GetComparatorOptions<Meta>,
): EqualityComparator<Meta>;
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,5 +85,5 @@
},
"sideEffects": false,
"types": "index.d.ts",
"version": "4.0.0"
"version": "4.0.1-beta.3"
}
2 changes: 1 addition & 1 deletion src/arrays.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createIsCircular } from './utils';

import type { InternalEqualityComparator } from './utils';
import type { InternalEqualityComparator } from '../index.d';

/**
* Whether the arrays are equal in value.
Expand Down
15 changes: 2 additions & 13 deletions src/comparator.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
import { isPlainObject, isPromiseLike, sameValueZeroEqual } from './utils';

import type {
CreateComparatorCreatorOptions,
EqualityComparator,
EqualityComparatorCreator,
TypeEqualityComparator,
} from './utils';

export interface CreateComparatorCreatorOptions<Meta> {
areArraysEqual: TypeEqualityComparator<any[], Meta>;
areDatesEqual: TypeEqualityComparator<Date, Meta>;
areMapsEqual: TypeEqualityComparator<Map<any, any>, Meta>;
areObjectsEqual: TypeEqualityComparator<Record<string, any>, Meta>;
areRegExpsEqual: TypeEqualityComparator<RegExp, Meta>;
areSetsEqual: TypeEqualityComparator<Set<any>, Meta>;
createIsNestedEqual: EqualityComparatorCreator<Meta>;
}
} from '../index.d';

const ARGUMENTS_TAG = '[object Arguments]';
const BOOLEAN_TAG = '[object Boolean]';
Expand Down
46 changes: 14 additions & 32 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,16 @@ import { areMapsEqual, areMapsEqualCircular } from './maps';
import { areObjectsEqual, areObjectsEqualCircular } from './objects';
import { areRegExpsEqual } from './regexps';
import { areSetsEqual, areSetsEqualCircular } from './sets';
import {
createDefaultIsNestedEqual,
EqualityComparator,
merge,
sameValueZeroEqual,
} from './utils';

import type { CreateComparatorCreatorOptions } from './comparator';

export { sameValueZeroEqual };
import { createDefaultIsNestedEqual, merge, sameValueZeroEqual } from './utils';

export type { CreateComparatorCreatorOptions } from './comparator';
export type {
import type {
BaseCircularMeta,
CreateComparatorCreatorOptions,
EqualityComparator,
EqualityComparatorCreator,
InternalEqualityComparator,
NativeEqualityComparator,
TypeEqualityComparator,
} from './utils';

export type BaseCircularMeta = Pick<
WeakMap<any, any>,
'delete' | 'get' | 'set'
>;
GetComparatorOptions,
} from '../index.d';

export type GetComparatorOptions<Meta> = (
defaultOptions: CreateComparatorCreatorOptions<Meta>,
) => Partial<CreateComparatorCreatorOptions<Meta>>;
export { sameValueZeroEqual };

const DEFAULT_CONFIG: CreateComparatorCreatorOptions<undefined> = Object.freeze(
{
Expand All @@ -45,16 +27,16 @@ const DEFAULT_CONFIG: CreateComparatorCreatorOptions<undefined> = Object.freeze(
createIsNestedEqual: createDefaultIsNestedEqual,
},
);
const DEFAULT_CIRCULAR_CONFIG: CreateComparatorCreatorOptions<
WeakMap<object, any>
> = Object.freeze(
merge(DEFAULT_CONFIG, {
const DEFAULT_CIRCULAR_CONFIG: CreateComparatorCreatorOptions<BaseCircularMeta> =
Object.freeze({
areArraysEqual: areArraysEqualCircular,
areDatesEqual,
areMapsEqual: areMapsEqualCircular,
areObjectsEqual: areObjectsEqualCircular,
areRegExpsEqual,
areSetsEqual: areSetsEqualCircular,
}),
);
createIsNestedEqual: createDefaultIsNestedEqual,
});

const isDeepEqual = createComparator(DEFAULT_CONFIG);

Expand Down Expand Up @@ -110,7 +92,7 @@ export function createCustomEqual<Meta = undefined>(
getComparatorOptions: GetComparatorOptions<Meta>,
): EqualityComparator<Meta> {
return createComparator<Meta>(
merge(DEFAULT_CONFIG, getComparatorOptions(DEFAULT_CONFIG)),
merge(DEFAULT_CONFIG, getComparatorOptions(DEFAULT_CONFIG as any)),
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/maps.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createIsCircular } from './utils';

import type { InternalEqualityComparator } from './utils';
import type { InternalEqualityComparator } from '../index.d';

/**
* Whether the `Map`s are equal in value.
Expand Down
3 changes: 2 additions & 1 deletion src/objects.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { createIsCircular } from './utils';

import type { InternalEqualityComparator } from './utils';
import type { InternalEqualityComparator } from '../index.d';

interface Dictionary<Value> {
[key: string]: Value;
$$typeof?: any;
}

const OWNER = '_owner';
Expand Down
2 changes: 1 addition & 1 deletion src/sets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createIsCircular } from './utils';

import type { InternalEqualityComparator } from './utils';
import type { InternalEqualityComparator } from '../index.d';

/**
* Whether the `Set`s are equal in value.
Expand Down
Loading