Skip to content

Commit

Permalink
fix(assert): accept abstract classes
Browse files Browse the repository at this point in the history
  • Loading branch information
0f-0b committed Sep 16, 2024
1 parent 05b6d7e commit f658829
Show file tree
Hide file tree
Showing 6 changed files with 21 additions and 19 deletions.
11 changes: 6 additions & 5 deletions assert/instance_of.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 AnyConstructor> = T extends // deno-lint-ignore no-explicit-any
new (...args: any) => infer C ? C
: never;
export type GetConstructorType<T extends AnyConstructor> = InstanceType<T>;

/**
* Make an assertion that `obj` is an instance of `type`.
Expand All @@ -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<T extends AnyConstructor>(
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<T> {
): asserts actual is InstanceType<T> {
if (actual instanceof expectedType) return;

const msgSuffix = msg ? `: ${msg}` : ".";
Expand Down
3 changes: 3 additions & 0 deletions assert/instance_of_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion assert/is_error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { stripAnsiCode } from "@std/internal/styles";
export function assertIsError<E extends Error = Error>(
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 {
Expand Down
2 changes: 1 addition & 1 deletion assert/not_instance_of.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { assertFalse } from "./false.ts";
export function assertNotInstanceOf<A, T>(
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<A, T> {
const msgSuffix = msg ? `: ${msg}` : ".";
Expand Down
11 changes: 5 additions & 6 deletions assert/rejects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,22 @@ export function assertRejects(
export function assertRejects<E extends Error = Error>(
fn: () => PromiseLike<unknown>,
// deno-lint-ignore no-explicit-any
ErrorClass: new (...args: any[]) => E,
ErrorClass: abstract new (...args: any[]) => E,
msgIncludes?: string,
msg?: string,
): Promise<E>;
export async function assertRejects<E extends Error = Error>(
fn: () => PromiseLike<unknown>,
errorClassOrMsg?:
// deno-lint-ignore no-explicit-any
| (new (...args: any[]) => E)
| (abstract new (...args: any[]) => E)
| string,
msgIncludesOrMsg?: string,
msg?: string,
): Promise<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") {
Expand All @@ -73,8 +73,7 @@ export async function assertRejects<E extends Error = Error>(
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 {
Expand Down
11 changes: 5 additions & 6 deletions assert/throws.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,22 +52,22 @@ export function assertThrows(
export function assertThrows<E extends Error = Error>(
fn: () => unknown,
// deno-lint-ignore no-explicit-any
ErrorClass: new (...args: any[]) => E,
ErrorClass: abstract new (...args: any[]) => E,
msgIncludes?: string,
msg?: string,
): E;
export function assertThrows<E extends Error = Error>(
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") {
Expand All @@ -76,8 +76,7 @@ export function assertThrows<E extends Error = Error>(
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;
Expand Down

0 comments on commit f658829

Please sign in to comment.