Skip to content

Commit

Permalink
Merge pull request #122 from jsr-core/fix-test-equal
Browse files Browse the repository at this point in the history
test[Equal]: fix false positive
  • Loading branch information
lambdalisue authored Aug 13, 2024
2 parents 0981e0d + ad2042b commit ae3696d
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
8 changes: 7 additions & 1 deletion _testutil.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { assertEquals } from "@std/assert";
import type { IsExact } from "@std/testing/types";
import type { Predicate } from "./type.ts";

const examples = {
Expand Down Expand Up @@ -51,9 +52,14 @@ export async function testWithExamples<T>(

// It seems 'IsExact' in deno_std is false positive so use `Equal` in type-challenges
// https://github.com/type-challenges/type-challenges/blob/e77262dba62e9254451f661cb4fe5517ffd1d933/utils/index.d.ts#L7-L9
export type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends
/** @deprecated use {@linkcode Equal} */
export type TypeChallengesEqual<X, Y> = (<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;

// `Equal` in type-challenges is false positive so combine `IsExact` + `Equal`.
export type Equal<X, Y> = TypeChallengesEqual<X, Y> extends true ? IsExact<X, Y>
: false;

export function stringify(x: unknown): string {
if (x instanceof Date) return `Date(${x.valueOf()})`;
if (x instanceof Promise) return "Promise";
Expand Down
43 changes: 43 additions & 0 deletions _testutil_test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// deno-lint-ignore-file no-explicit-any
import { assertType, type IsExact } from "@std/testing/types";

import type { Equal, TypeChallengesEqual } from "./_testutil.ts";

declare class Foo<T> {
declare private _: T;
}

Deno.test("IsExact gives false positive", () => {
// all of the following should be false
assertType<IsExact<() => void, (x?: number) => void>>(true);
assertType<IsExact<Foo<{ x: 1; a?: 1 }>, Foo<{ x: 1; b?: 1 }>>>(true);
assertType<IsExact<() => any, () => number>>(true);
assertType<IsExact<Foo<any>, Foo<number>>>(true);
assertType<IsExact<{ a: 1 }, { readonly a: 1 }>>(true);
});

Deno.test("TypeChallengesEqual gives false positive", () => {
// all of the following should be false
assertType<TypeChallengesEqual<[...any[]], [...any[], any]>>(true);
assertType<TypeChallengesEqual<[any, ...any[]], [any, ...any[], any]>>(true);
});

Deno.test("Equal", async (t) => {
await t.step(
"should be correct in cases where IsExact gives false positive",
() => {
assertType<Equal<() => void, (x?: number) => void>>(false);
assertType<Equal<Foo<{ x: 1; a?: 1 }>, Foo<{ x: 1; b?: 1 }>>>(false);
assertType<Equal<() => any, () => number>>(false);
assertType<Equal<Foo<any>, Foo<number>>>(false);
assertType<Equal<{ a: 1 }, { readonly a: 1 }>>(false);
},
);
await t.step(
"should be correct in cases where TypeChallengesEqual gives false positive",
() => {
assertType<Equal<[...any[]], [...any[], any]>>(false);
assertType<Equal<[any, ...any[]], [any, ...any[], any]>>(false);
},
);
});

0 comments on commit ae3696d

Please sign in to comment.