-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add TypeScript types #34
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
import type { Boom } from "@hapi/boom"; | ||
import type { AssertionError } from "assert"; | ||
|
||
export type BounceErrorType = Error | "system" | "boom" | Record<any, any>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
export interface BounceOptions { | ||
/** | ||
* An object which is assigned to the `err`, copying the properties onto the error. | ||
*/ | ||
decorate?: Record<any, any>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, |
||
|
||
/** | ||
* An error used to override `err` when `err` matches. If used with `decorate`, the `override` object is modified. | ||
*/ | ||
override?: Error; | ||
|
||
/** | ||
* If `true`, the error is returned instead of thrown. Defaults to `false`. | ||
* @defaultValue `false` | ||
*/ | ||
return?: boolean; | ||
} | ||
|
||
/** | ||
* A single item or an array of items of: | ||
* - An error constructor (e.g. `SyntaxError`). | ||
* - `'system'` - matches any languange native error or node assertions. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "languange" => "language" |
||
* - `'boom'` - matches [**boom**](https://github.com/hapijs/boom) errors. | ||
* - an object where each property is compared with the error and must match the error property | ||
* value. All the properties in the object must match the error but do not need to include all | ||
* the error properties. | ||
*/ | ||
export type BounceErrorTypes = BounceErrorType | BounceErrorType[]; | ||
|
||
export type BounceReturn< | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice. I would probably have used function overloads to handle this, but this seems cleaner. |
||
TErr extends Error, | ||
TOpts extends BounceOptions | ||
> = TOpts extends { return: true } | ||
? TOpts extends { decorate: any } | ||
? (TOpts extends { override: any } ? TOpts["override"] : TErr) & | ||
TOpts["decorate"] | ||
: TOpts extends { override: any } | ||
? TOpts["override"] | ||
: TErr | ||
: void; | ||
|
||
/** | ||
* Throws the error passed if it matches any of the specified rules where: | ||
* - `err` - the error. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment line is redundant. |
||
* | ||
* @param err The error. | ||
* @param types {@link BounceErrorTypes} | ||
* @param options {@link BounceOptions} | ||
*/ | ||
export function rethrow<TErr extends Error, TOpts extends BounceOptions>( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would allow the try {
// whatever
} catch (err) {
Bounce.rethrow(err, 'system');
// do your thing...
} |
||
err: TErr, | ||
types: BounceErrorTypes, | ||
options?: TOpts | ||
): BounceReturn<TErr, TOpts>; | ||
|
||
/** | ||
* The opposite action of {@link rethrow `rethrow()`}. Ignores any errors matching the specified `types`. Any error not matching is thrown after applying the `options`. | ||
* | ||
* @param err The error. | ||
* @param types same as the {@link BounceErrorTypes `types`} argument passed to `rethrow()` | ||
* @param options same as the {@link BounceOptions `options`} argument passed to `rethrow()` | ||
*/ | ||
export function ignore<TErr extends Error, TOpts extends BounceOptions>( | ||
err: TErr, | ||
types: BounceErrorTypes, | ||
options?: TOpts | ||
): BounceReturn<TErr, TOpts>; | ||
|
||
/** | ||
* Awaits for the value to resolve in the background and then apply either the `rethrow()` or `ignore()` actions. | ||
* | ||
* @param operation a function, promise, or value that is `await`ed on inside a `try...catch` and any error thrown processed by the `action` rule. | ||
* @param action one of `'rethrow'` or `'ignore'`. Defaults to `'rethrow'`. | ||
* @param types same as the `types` argument passed to `rethrow()` or `ignore()`. Defaults to `'system'`. | ||
* @param options same as the {@link BounceOptions `options`} argument passed to `rethrow()` or `ignore()`. | ||
*/ | ||
export function background( | ||
operation: Function | Promise<any> | any, | ||
action?: "rethrow" | "ignore", | ||
types?: BounceErrorTypes, | ||
options?: BounceOptions | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be |
||
): Promise<void>; | ||
|
||
/** | ||
* Returns `true` when `err` is a [**boom**](https://github.com/hapijs/boom) error. | ||
* | ||
* @param err The error. | ||
*/ | ||
export function isBoom(err: unknown): err is Boom; | ||
kanongil marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* Returns `true` when `err` is an error. | ||
* | ||
* @param err The error. | ||
*/ | ||
export function isError(err: unknown): err is Error; | ||
kanongil marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/** | ||
* Return `true` when `err` is one of: | ||
* - `EvalError` | ||
* - `RangeError` | ||
* - `ReferenceError` | ||
* - `SyntaxError` | ||
* - `TypeError` | ||
* - `URIError` | ||
* - Node's `AssertionError` | ||
* | ||
* @param err The error. | ||
*/ | ||
export function isSystem( | ||
err: unknown | ||
): err is | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The predicate is missing the In reality, I would just return a simple There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, I think this is the better: export function isSystem(err: Error): boolean;
export function isSystem(err: unknown): err is Error; |
||
| EvalError | ||
| RangeError | ||
| ReferenceError | ||
| SyntaxError | ||
| TypeError | ||
| URIError | ||
| AssertionError; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
import * as Bounce from ".."; | ||
import * as Boom from "@hapi/boom"; | ||
import * as Lab from "@hapi/lab"; | ||
|
||
const { expect } = Lab.types; | ||
|
||
class CustomErr extends Error { | ||
customProp = "customProp"; | ||
} | ||
|
||
// rethrow | ||
expect.type<void>(Bounce.rethrow(new Error(), "system")); | ||
expect.type<void>(Bounce.rethrow(new Error(), "boom")); | ||
expect.type<void>(Bounce.rethrow(new Error(), ["system", "boom"])); | ||
expect.type<void>(Bounce.rethrow(new Error(), { prop: "prop" })); | ||
expect.type<void>( | ||
Bounce.rethrow(new Error(), "system", { decorate: { prop: "prop" } }) | ||
); | ||
expect.type<void>( | ||
Bounce.rethrow(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
}) | ||
); | ||
expect.type<CustomErr & { prop: string }>( | ||
Bounce.rethrow(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<CustomErr>( | ||
Bounce.rethrow(new Error(), "system", { | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Error>(Bounce.rethrow(new Error(), "system", { return: true })); | ||
expect.type<Error & { prop: string }>( | ||
Bounce.rethrow(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
return: true, | ||
}) | ||
); | ||
|
||
expect.error(Bounce.rethrow(new Error(), "systm")); | ||
expect.error(Bounce.rethrow(new Error(), "bom")); | ||
expect.error(Bounce.rethrow(new Error(), ["system", "bom"])); | ||
expect.error(Bounce.rethrow(new Error(), "system", { decorate: true })); | ||
expect.error( | ||
Bounce.rethrow(new Error(), "system", { override: { prop: "prop" } }) | ||
); | ||
expect.error(Bounce.rethrow(new Error(), "system", { return: 1 })); | ||
|
||
// ignore | ||
expect.type<void>(Bounce.ignore(new TypeError(), "system")); | ||
expect.type<void>(Bounce.ignore(Boom.internal(), "boom")); | ||
expect.type<void>(Bounce.ignore(new CustomErr(), { customProp: "customProp" })); | ||
expect.type<void>( | ||
Bounce.ignore(new TypeError(), "system", { decorate: { prop: "prop" } }) | ||
); | ||
expect.type<void>( | ||
Bounce.ignore(new TypeError(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
}) | ||
); | ||
expect.type<CustomErr & { prop: string }>( | ||
Bounce.ignore(new TypeError(), "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<CustomErr>( | ||
Bounce.ignore(new Error(), "system", { | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Error>(Bounce.ignore(new Error(), "system", { return: true })); | ||
expect.type<Error & { prop: string }>( | ||
Bounce.ignore(new Error(), "system", { | ||
decorate: { prop: "prop" }, | ||
return: true, | ||
}) | ||
); | ||
|
||
expect.error(Bounce.ignore(new Error(), "systm")); | ||
expect.error(Bounce.ignore(new Error(), "bom")); | ||
expect.error(Bounce.ignore(new Error(), "system", { decorate: true })); | ||
expect.error( | ||
Bounce.ignore(new TypeError(), "system", { override: { prop: "prop" } }) | ||
); | ||
expect.error(Bounce.ignore(new Error(), "system", { return: 1 })); | ||
|
||
// background | ||
expect.type<Promise<void>>(Bounce.background(() => {})); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow")); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "ignore")); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow", "system")); | ||
expect.type<Promise<void>>(Bounce.background(() => {}, "rethrow", "boom")); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", { prop: "prop" }) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
override: new CustomErr(), | ||
return: true, | ||
}) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { return: true }) | ||
); | ||
expect.type<Promise<void>>( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
decorate: { prop: "prop" }, | ||
return: true, | ||
}) | ||
); | ||
|
||
expect.error(Bounce.background(() => {}, "rethro")); | ||
expect.error(Bounce.background(() => {}, "ignor")); | ||
expect.error(Bounce.background(() => {}, "rethrow", "systm")); | ||
expect.error(Bounce.background(() => {}, "rethrow", "bom")); | ||
expect.error( | ||
Bounce.background(() => {}, "rethrow", "system", { decorate: true }) | ||
); | ||
expect.error( | ||
Bounce.background(() => {}, "rethrow", "system", { | ||
override: { prop: "prop" }, | ||
}) | ||
); | ||
expect.error(Bounce.background(() => {}, "rethrow", "system", { return: 1 })); | ||
|
||
// isBoom | ||
expect.type<boolean>(Bounce.isBoom("")); | ||
|
||
// isError | ||
expect.type<boolean>(Bounce.isError("")); | ||
|
||
// isSystem | ||
expect.type<boolean>(Bounce.isError("")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error
is incorrect, it should beErrorConstructor
. This doesn't actually change anything, sinceRecord<any, any>
matches bothError
andErrorConstructor
.