From f658829836aa485a00029c64121c8577008c6c92 Mon Sep 17 00:00:00 2001 From: ud2 Date: Sat, 14 Sep 2024 21:35:30 +0800 Subject: [PATCH] fix(assert): accept abstract classes --- assert/instance_of.ts | 11 ++++++----- assert/instance_of_test.ts | 3 +++ assert/is_error.ts | 2 +- assert/not_instance_of.ts | 2 +- assert/rejects.ts | 11 +++++------ assert/throws.ts | 11 +++++------ 6 files changed, 21 insertions(+), 19 deletions(-) diff --git a/assert/instance_of.ts b/assert/instance_of.ts index fbce7385d043..98f852b32b8f 100644 --- a/assert/instance_of.ts +++ b/assert/instance_of.ts @@ -6,9 +6,7 @@ import { AssertionError } from "./assertion_error.ts"; // deno-lint-ignore no-explicit-any export type AnyConstructor = new (...args: any[]) => any; /** Gets constructor type */ -export type GetConstructorType = T extends // deno-lint-ignore no-explicit-any -new (...args: any) => infer C ? C - : never; +export type GetConstructorType = InstanceType; /** * Make an assertion that `obj` is an instance of `type`. @@ -27,11 +25,14 @@ new (...args: any) => infer C ? C * @param expectedType The expected class constructor. * @param msg The optional message to display if the assertion fails. */ -export function assertInstanceOf( +export function assertInstanceOf< + // deno-lint-ignore no-explicit-any + T extends abstract new (...args: any[]) => any, +>( actual: unknown, expectedType: T, msg = "", -): asserts actual is GetConstructorType { +): asserts actual is InstanceType { if (actual instanceof expectedType) return; const msgSuffix = msg ? `: ${msg}` : "."; diff --git a/assert/instance_of_test.ts b/assert/instance_of_test.ts index b728c4520de5..fcb4552fbc3e 100644 --- a/assert/instance_of_test.ts +++ b/assert/instance_of_test.ts @@ -7,12 +7,15 @@ Deno.test({ class TestClass1 {} class TestClass2 {} class TestClass3 {} + abstract class AbstractTestClass {} + class ConcreteTestClass extends AbstractTestClass {} // Regular types assertInstanceOf(new Date(), Date); assertInstanceOf(new Number(), Number); assertInstanceOf(Promise.resolve(), Promise); assertInstanceOf(new TestClass1(), TestClass1); + assertInstanceOf(new ConcreteTestClass(), AbstractTestClass); // Throwing cases assertThrows( diff --git a/assert/is_error.ts b/assert/is_error.ts index 20bac9acc9db..58a09f9ce276 100644 --- a/assert/is_error.ts +++ b/assert/is_error.ts @@ -29,7 +29,7 @@ import { stripAnsiCode } from "@std/internal/styles"; export function assertIsError( error: unknown, // deno-lint-ignore no-explicit-any - ErrorClass?: new (...args: any[]) => E, + ErrorClass?: abstract new (...args: any[]) => E, msgMatches?: string | RegExp, msg?: string, ): asserts error is E { diff --git a/assert/not_instance_of.ts b/assert/not_instance_of.ts index 284ce3c7dc9e..3d785233be40 100644 --- a/assert/not_instance_of.ts +++ b/assert/not_instance_of.ts @@ -23,7 +23,7 @@ import { assertFalse } from "./false.ts"; export function assertNotInstanceOf( actual: A, // deno-lint-ignore no-explicit-any - unexpectedType: new (...args: any[]) => T, + unexpectedType: abstract new (...args: any[]) => T, msg?: string, ): asserts actual is Exclude { const msgSuffix = msg ? `: ${msg}` : "."; diff --git a/assert/rejects.ts b/assert/rejects.ts index 699d74a91d0b..db585a9d6c3a 100644 --- a/assert/rejects.ts +++ b/assert/rejects.ts @@ -49,7 +49,7 @@ export function assertRejects( export function assertRejects( fn: () => PromiseLike, // deno-lint-ignore no-explicit-any - ErrorClass: new (...args: any[]) => E, + ErrorClass: abstract new (...args: any[]) => E, msgIncludes?: string, msg?: string, ): Promise; @@ -57,14 +57,14 @@ export async function assertRejects( fn: () => PromiseLike, errorClassOrMsg?: // deno-lint-ignore no-explicit-any - | (new (...args: any[]) => E) + | (abstract new (...args: any[]) => E) | string, msgIncludesOrMsg?: string, msg?: string, ): Promise { // deno-lint-ignore no-explicit-any - let ErrorClass: (new (...args: any[]) => E) | undefined = undefined; - let msgIncludes: string | undefined = undefined; + let ErrorClass: (abstract new (...args: any[]) => E) | undefined; + let msgIncludes: string | undefined; let err; if (typeof errorClassOrMsg !== "string") { @@ -73,8 +73,7 @@ export async function assertRejects( errorClassOrMsg.prototype instanceof Error || errorClassOrMsg.prototype === Error.prototype ) { - // deno-lint-ignore no-explicit-any - ErrorClass = errorClassOrMsg as new (...args: any[]) => E; + ErrorClass = errorClassOrMsg; msgIncludes = msgIncludesOrMsg; } } else { diff --git a/assert/throws.ts b/assert/throws.ts index 356ab002eeb9..49c0c5d8e165 100644 --- a/assert/throws.ts +++ b/assert/throws.ts @@ -52,7 +52,7 @@ export function assertThrows( export function assertThrows( fn: () => unknown, // deno-lint-ignore no-explicit-any - ErrorClass: new (...args: any[]) => E, + ErrorClass: abstract new (...args: any[]) => E, msgIncludes?: string, msg?: string, ): E; @@ -60,14 +60,14 @@ export function assertThrows( fn: () => unknown, errorClassOrMsg?: // deno-lint-ignore no-explicit-any - | (new (...args: any[]) => E) + | (abstract new (...args: any[]) => E) | string, msgIncludesOrMsg?: string, msg?: string, ): E | Error | unknown { // deno-lint-ignore no-explicit-any - let ErrorClass: (new (...args: any[]) => E) | undefined = undefined; - let msgIncludes: string | undefined = undefined; + let ErrorClass: (abstract new (...args: any[]) => E) | undefined; + let msgIncludes: string | undefined; let err; if (typeof errorClassOrMsg !== "string") { @@ -76,8 +76,7 @@ export function assertThrows( errorClassOrMsg?.prototype instanceof Error || errorClassOrMsg?.prototype === Error.prototype ) { - // deno-lint-ignore no-explicit-any - ErrorClass = errorClassOrMsg as new (...args: any[]) => E; + ErrorClass = errorClassOrMsg; msgIncludes = msgIncludesOrMsg; } else { msg = msgIncludesOrMsg;