The @perfective/common/error package helps organize exceptions and error handling.
It defines an Exception, based on the JS
Error class,
that supports localizable error messages and error chaining;
and provides functions to handle error stack output.
Exception type definition.class Exception extends Error {
public readonly name: string = 'Exception';
public message: string; // (1)
public readonly template: string; // (2)
public readonly tokens: ExceptionTokens; // (3)
public readonly context: ExceptionContext; // (4)
public readonly previous: Error | null; // (5)
public toString(): string; // (6)
}-
Inherited from
Error, message is generated from thetemplateandtokens. -
Message template with tokens wrapped in
{{ }}, e.g.User ID {{id}}orUser {{user_id}}. -
Token/Value map to be used in the error message.
-
Additional context information. Context is not rendered by default, but may be useful in applications.
-
Provide a previous error, if exists.
-
Human-readable output of all the errors.
-
exception(message: string, tokens: ExceptionTokens = {}, context: ExceptionContext = {}): Exception— creates anException. -
chained(message: string, tokens: ExceptionTokens = {}, context: ExceptionContext = {}): (previous: Error) ⇒ Exception— creates a function to wrap a previousErrorinto anException. -
causedBy(previous: Error, message: string, tokens: ExceptionTokens = {}, context: ExceptionContext = {}): Exception— creates anExceptionwith a previousError. -
caughtError(value: unknown): Error | Exception— wraps a non-Errorvalueinto anException. TheException.messagestarts withCaughtand contains the caughtvaluecoerced to a string.If given an
Error, returns it as is.
-
invalidArgumentException(argument: string, expected: string, actual: string): Exception— creates an exception with the message about an invalid argument.
import { causedBy, chainStack, exception, rethrows, throws } from '@perfective/common/error';
import { decimal } from '@perfective/common/number';
function positive(input: number): string {
if (input <= 0) {
return throws(exception('Invalid input {{input}}', { // (1)
input: decimal(input);
}));
}
return decimal(10);
}
function field(name: string, value: number): string {
try {
return `${name} = ${positive(value)}`;
}
catch (error) {
return throws(causedBy(error, 'Failed to output field {{field}}', { // (2)
field: name,
}));
}
}
function record(): Record<string, string> {
try {
return {
username: field('username', -42),
}
}
catch (error) {
return rethrows(error, 'Failed to build a record'); // (3)
}
}
try {
record();
}
catch (error) {
console.error(error.toString()); // (4)
// Outputs:
// Exception: Failed to build a record
// - Exception: Failed to output field `username`
// - Exception: Invalid input `-42`
console.error(chainStack(error)); // (5)
// Outputs:
// Exception: Failed to build a record
// at Object.rethrows (...)
// at Object.record (...)
// ...
// Caused by: Exception: Failed to output field `username`
// at Object.causedBy (...)
// at Object.throws (...)
// at Object.field (...)
// ...
// Caused by: Exception: Invalid input `-42`
// at Object.exception (...)
// at Object.throws (...)
// at Object.positive (...)
// ...
}-
throwscan be used with anyErrortype, butExceptionsupports passing context information separately, which can be convenient for localization or logging purposes. -
causedByis a function to create anExceptionwith a presentException.previousproperty. -
rethrowsis a shortcut for thethrows(causedBy())call. It supports message context as well. -
error.toString()is explicitly re-defined onExceptionto output all error messages. -
chainStack()allows to output all errors with their stack information (platform dependent).
type Panic = (cause?: unknown) ⇒ never
— a function that throws an Error.
-
panic(message: string, tokens?: ExceptionTokens, context?: ExceptionContext): Panic— creates a function that throws anExceptionwith a givenmessagetemplate withtokensand additionalcontextdata. If thecauseis defined, sets thecauseas apreviouserror.Useful working with
Promise.catch()and RxJScatchError(). -
panic<E extends Error>(error: Value<E>): Panic— creates a function that throws a givenError. Ignores thecause, even when if is defined.Usepanicto create a callback for lazy evaluation.import { panic } from '@perfective/common/error'; import { maybe } from '@perfective/common/maybe'; export function example(input: string | null | undefined): string { return maybe(input) .or(panic('Input is not present')); // (1) }
-
Must use
panic(), as the fallback inMaybe.or()is called only when theinputis not present. Usingthrows()will result in throwing an exception every time a function is called.
-
-
throws(message: string, tokens?: ExceptionTokens, context?: ExceptionContext): never— throws anExceptionwith a givenmessagetemplate withtokensand additionalcontextdata. -
throws<E extends Error>(error: Value<E>): never— throws a givenError. If given a callback, throws anErrorreturned by the callback.Can be used to throw an exception from a one-line arrow function.
-
rethrows(previous: Error, message: string, tokens: ExceptionTokens = {}, context: ExceptionContext = {}): never— throws anExceptionwith a givenmessagecaused by apreviousError. Exception message may contain giventokensand additionalcontextdata.Similar to
throws, but requires to provide a previous error.
type Recovery<T> = (error: Error) ⇒ T
— a function that handles a given Error and returns a recovery value.
The default JS Error class does not have toJSON method
and is serialized as an empty object by JSON.stringify.
This creates a problem for any attempt to transfer error information.
Type Failure solved this problem by providing a record type to "serialize" Error and Exception.
It omits stack information, but keeps the list of previous errors.
-
Failure-
failure<E extends Error>(error: E): Failure— convert andErroror anExceptioninto aFailurerecord.
-
-
-
error(message: string): Error— instantiates a newError. -
isError<T>(value: Error | T): value is Error— returnstruewhen the value is an instance ofError. -
isNotError<T>(value: Error | T): value is T— returnstruewhen the value is not an instance ofError.
-
-
-
evalError(message: string): EvalError— instantiates a newEvalError. -
isEvalError<T>(value: EvalError | T): value is EvalError— returnstruewhen the value is an instance ofEvalError. -
isNotEvalError<T>(value: EvalError | T): value is T— returnstruewhen the value is not an instance ofEvalError.
-
-
-
rangeError(message: string): RangeError— instantiates a newRangeError. -
isRangeError<T>(value: RangeError | T): value is RangeError— returnstruewhen the value is an instance ofRangeError. -
isNotRangeError<T>(value: RangeError | T): value is T— returnstruewhen the value is not an instance ofRangeError.
-
-
-
referenceError(message: string): ReferenceError— instantiates a newReferenceError. -
isReferenceError<T>(value: ReferenceError | T): value is ReferenceError— returnstruewhen the value is an instance ofReferenceError. -
isNotReferenceError<T>(value: ReferenceError | T): value is T— returnstruewhen the value is not an instance ofReferenceError.
-
-
-
syntaxError(message: string): SyntaxError— instantiates a newSyntaxError. -
isSyntaxError<T>(value: SyntaxError | T): value is SyntaxError— returnstruewhen the value is an instance ofSyntaxError. -
isNotSyntaxError<T>(value: SyntaxError | T): value is T— returnstruewhen the value is not an instance ofSyntaxError.
-
-
-
typeError(message: string): TypeError— instantiates a newTypeError. -
isTypeError<T>(value: TypeError | T): value is TypeError— returnstruewhen the value is an instance ofTypeError. -
isNotTypeError<T>(value: TypeError | T): value is T— returnstruewhen the value is not an instance ofTypeError.
-
|
Note
|
|
-
Provide functions to parse standard error messages and predicates to check for them.