Skip to content

Commit

Permalink
Add IsEqual type
Browse files Browse the repository at this point in the history
  • Loading branch information
doz13189 committed Nov 26, 2022
1 parent 60a213f commit 5d58998
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 17 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Expand Up @@ -74,6 +74,7 @@ export type {RequiredKeysOf} from './source/required-keys-of';
export type {HasRequiredKeys} from './source/has-required-keys';
export type {Spread} from './source/spread';
export type {TupleToUnion} from './source/tuple-to-union';
export type {IsEqual} from './source/is-equal';

// Template literal types
export type {CamelCase} from './source/camel-case';
Expand Down
1 change: 1 addition & 0 deletions readme.md
Expand Up @@ -183,6 +183,7 @@ Click the type names for complete docs.
- [`RequiredKeysOf`](source/required-keys-of.d.ts) - Extract all required keys from the given type.
- [`HasRequiredKeys`](source/has-required-keys.d.ts) - Create a `true`/`false` type depending on whether the given type has any required fields.
- [`Spread`](source/spread.d.ts) - Mimic the type inferred by TypeScript when merging two objects or two arrays/tuples using the spread syntax.
- [`IsEqual`](source/is-equal.ts) - Returns a boolean for whether the two given types are equal.

### JSON

Expand Down
2 changes: 1 addition & 1 deletion source/conditional-pick-deep.d.ts
@@ -1,5 +1,5 @@
import type {Opaque} from './opaque';
import type {IsEqual} from './internal';
import type {IsEqual} from './is-equal';
import type {ConditionalExcept} from './conditional-except';
import type {ConditionalSimplifyDeep} from './conditional-simplify';

Expand Down
2 changes: 1 addition & 1 deletion source/except.d.ts
@@ -1,4 +1,4 @@
import type {IsEqual} from './internal';
import type {IsEqual} from './is-equal';

/**
Filter out keys from an object.
Expand Down
2 changes: 1 addition & 1 deletion source/includes.d.ts
@@ -1,4 +1,4 @@
import type {IsEqual} from './internal';
import type {IsEqual} from './is-equal';

/**
Returns a boolean for whether the given array includes the given item.
Expand Down
12 changes: 0 additions & 12 deletions source/internal.d.ts
@@ -1,17 +1,5 @@
import type {Primitive} from './primitive';

/**
Returns a boolean for whether the two given types are equal.
@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
@link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796
*/
export type IsEqual<T, U> =
(<G>() => G extends T ? 1 : 2) extends
(<G>() => G extends U ? 1 : 2)
? true
: false;

/**
Infer the length of the given array `<T>`.
Expand Down
21 changes: 21 additions & 0 deletions source/is-equal.d.ts
@@ -0,0 +1,21 @@
/**
Returns a boolean for whether the two given types are equal.
@link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
@link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796
@example
```
import type {IsEqual} from 'type-fest';
type Expect<T extends true> = T
type Case = Expect<IsEqual<Uppercase<"sample">, "SAMPLE">>
```
@category Utilities
*/
export type IsEqual<X, Y> =
(<G>() => G extends X ? 1 : 2) extends
(<G>() => G extends Y ? 1 : 2)
? true
: false;
3 changes: 2 additions & 1 deletion source/multidimensional-array.d.ts
@@ -1,4 +1,5 @@
import type {IsEqual, Subtract} from './internal';
import type {Subtract} from './internal';
import type {IsEqual} from './is-equal';

type Recursive<T> = Array<Recursive<T>>;

Expand Down
3 changes: 2 additions & 1 deletion source/multidimensional-readonly-array.d.ts
@@ -1,4 +1,5 @@
import type {IsEqual, Subtract} from './internal';
import type {Subtract} from './internal';
import type {IsEqual} from './is-equal';

type Recursive<T> = ReadonlyArray<Recursive<T>>;

Expand Down
28 changes: 28 additions & 0 deletions test-d/is-equal.ts
@@ -0,0 +1,28 @@
import {expectError, expectType} from 'tsd';
import type {IsEqual} from '../index';

const notEqualNumberAndString: IsEqual<number, string> = false;
expectType<false>(notEqualNumberAndString);

const equalNumbers: IsEqual<1, 1> = true;
expectType<true>(equalNumbers);

const notEqualAnyAndNumber: IsEqual<any, number> = false;
expectType<false>(notEqualAnyAndNumber);

const notEqualUnionAndNumber: IsEqual<1 | 2, 1> = false;
expectType<false>(notEqualUnionAndNumber);

const notEqualAnyAndNever: IsEqual<any, never> = false;
expectType<false>(notEqualAnyAndNever);

const notEqualArrayOfAnyAndArrayOfNever: IsEqual<[any], [never]> = false;
expectType<false>(notEqualArrayOfAnyAndArrayOfNever);

declare const anything: any;

// Missing all generic parameters.
expectError<IsEqual>(anything);

// Missing `Y` generic parameter.
expectError<IsEqual<number>>(anything);

0 comments on commit 5d58998

Please sign in to comment.