diff --git a/packages/core/src/lib/helpers/TypeFactories.ts b/packages/core/src/lib/helpers/TypeFactories.ts index 90999f6..d09d11f 100644 --- a/packages/core/src/lib/helpers/TypeFactories.ts +++ b/packages/core/src/lib/helpers/TypeFactories.ts @@ -2,6 +2,7 @@ import { ArrayAssertion } from "../ArrayAssertion"; import { Assertion, Constructor } from "../Assertion"; import { BooleanAssertion } from "../BooleanAssertion"; import { DateAssertion } from "../DateAssertion"; +import { ErrorAssertion } from "../ErrorAssertion"; import { type AnyFunction, FunctionAssertion } from "../FunctionAssertion"; import { NumberAssertion } from "../NumberAssertion"; import { ObjectAssertion } from "../ObjectAssertion"; @@ -47,6 +48,10 @@ export interface StaticTypeFactories { * A `Date` TypeFactory. */ Date: TypeFactory; + /** + * An `Error` TypeFactory. + */ + Error: TypeFactory>; /** * A `function` TypeFactory. */ @@ -71,6 +76,20 @@ export interface StaticTypeFactories { * @param innerType the TypeFactory for the array type */ array(innerType?: TypeFactory>): TypeFactory>; + /** + * Creates an `Error` TypeFactory for a specific error constructor. + * + * @example + * ``` + * class CustomError extends Error { ... } + * + * TypeFactories.error(CustomError); // a `CustomError` error factory + * ``` + * + * @typeParam T the type of the error constructor + * @param Type the error constructor + */ + error(Type: Constructor): TypeFactory>; /** * Creates a TypeFactory for an instance of the given constructor. * @@ -114,6 +133,11 @@ export const TypeFactories: Readonly = { predicate: (value): value is Date => value instanceof Date, typeName: Date.name, }, + Error: { + Factory: ErrorAssertion, + predicate: (value): value is Error => value instanceof Error, + typeName: Error.name, + }, Function: { Factory: FunctionAssertion, predicate: (value): value is AnyFunction => typeof value === "function", @@ -139,6 +163,13 @@ export const TypeFactories: Readonly = { typeName: "array", }; }, + error(Type: Constructor) { + return { + Factory: ErrorAssertion, + predicate: (value): value is T => value instanceof Type, + typeName: Type.name, + }; + }, instanceOf(type: Constructor) { return { Factory: Assertion, diff --git a/packages/core/test/lib/helpers/TypeFactories.test.ts b/packages/core/test/lib/helpers/TypeFactories.test.ts index b3101d2..4f9bb99 100644 --- a/packages/core/test/lib/helpers/TypeFactories.test.ts +++ b/packages/core/test/lib/helpers/TypeFactories.test.ts @@ -2,6 +2,17 @@ import { TypeFactories } from "../../../src/lib/helpers/TypeFactories"; import assert from "assert"; +class CustomError extends Error { + + public constructor(message?: string) { + super(message); + + this.name = this.constructor.name; + Error.captureStackTrace(this, this.constructor); + Object.setPrototypeOf(this, CustomError.prototype); + } +} + describe("[Unit] TypeFactories.test.ts", () => { describe(".predicate", () => { describe("#Boolean", () => { @@ -42,6 +53,24 @@ describe("[Unit] TypeFactories.test.ts", () => { }); }); + describe("#Error", () => { + context("when the value is an Error", () => { + it("returns true", () => { + const result = TypeFactories.Error.predicate(new Error("foo")); + + assert.equal(result, true); + }); + }); + + context("when the value is not an Error", () => { + it("returns false", () => { + const result = TypeFactories.Error.predicate("foo"); + + assert.equal(result, false); + }); + }); + }); + describe("#Function", () => { context("when the value is a function", () => { it("returns true", () => { @@ -143,6 +172,24 @@ describe("[Unit] TypeFactories.test.ts", () => { }); }); + describe(".error", () => { + context("when the value is an instace o the error type", () => { + it("returns true", () => { + const result = TypeFactories.error(CustomError).predicate(new CustomError("foo")); + + assert.equal(result, true); + }); + }); + + context("when the value is not an instace o the error type", () => { + it("returns false", () => { + const result = TypeFactories.error(CustomError).predicate(new Error("foo")); + + assert.equal(result, false); + }); + }); + }); + describe(".instanceOf", () => { context("when the value is an instance of the passed type", () => { it("returns true", () => {