info is required exactly when the info map's entry for code is not
undefined-able — that requiredness is what makes the per-code info
types of is and match sound.
Subclasses normally do not declare a constructor (a super call
cannot resolve the conditional info tuple while the code parameter is
still generic). name is set from the runtime class name automatically;
declare a field (override name = 'XError') if it must survive
minification.
OptionalcauseThe cause of the error.
ReadonlycodeOptionalstackStaticstackThe Error.stackTraceLimit property specifies the number of stack frames
collected by a stack trace (whether generated by new Error().stack or
Error.captureStackTrace(obj)).
The default value is 10 but may be set to any valid JavaScript number. Changes
will affect any stack trace captured after the value has been changed.
If set to a non-number value, or set to a negative number, stack traces will not capture any frames.
StaticcaptureCreates a .stack property on targetObject, which when accessed returns
a string representing the location in the code at which
Error.captureStackTrace() was called.
const myObject = {};
Error.captureStackTrace(myObject);
myObject.stack; // Similar to `new Error().stack`
The first line of the trace will be prefixed with
${myObject.name}: ${myObject.message}.
The optional constructorOpt argument accepts a function. If given, all frames
above constructorOpt, including constructorOpt, will be omitted from the
generated stack trace.
The constructorOpt argument is useful for hiding implementation
details of error generation from the user. For instance:
function a() {
b();
}
function b() {
c();
}
function c() {
// Create an error without stack trace to avoid calculating the stack trace twice.
const { stackTraceLimit } = Error;
Error.stackTraceLimit = 0;
const error = new Error();
Error.stackTraceLimit = stackTraceLimit;
// Capture the stack trace above function b
Error.captureStackTrace(error, b); // Neither function c, nor b is included in the stack trace
throw error;
}
a();
OptionalconstructorOpt: FunctionCreate .stack property on a target object
OptionalconstructorOpt: FunctionStaticfromNot callable on the base class — override in a domain subclass and fall back
to UnexpectedError.fromAny(e) so E stays specific. Use UnexpectedError.try
when you have no domain error type yet.
StaticisType guard for "is this error mine, and (optionally) one of these codes?".
Narrows unknown to the subclass instance, and — when codes are given —
narrows code and info (via IsCode) to just those codes,
replacing the e.code as XErrorCode cast that a wide Err union
otherwise forces. Union members that are already narrower than the class
(e.g. XError<A> in XError<A> | YError<B>) are kept as-is, so a
following match still exhausts only the value's codes.
The value to test (usually an Err payload of a wide union).
Whether e is an instance of this class.
Type guard narrowing to this class and one of codes.
The predicate (IsCode) is computed from the argument's type, so
on a distributed union (XError<A> | XError<B>, the shape produced by
narrowly-typed factories) a fully matched member is also subtracted
in the false branch — recovering one code inside orElse trims it from
the resulting error union, exactly like === narrowing on code. A
single wide instantiation (XError<A | B>) cannot be subtracted from;
for exhaustively mapping codes, use match.
Whether e is an instance of this class with a matching code.
StaticisIndicates whether the argument provided is a built-in Error instance or not.
Check if a value is an instance of Error
The value to check
True if the value is an instance of Error, false otherwise
StaticmatchExhaustively map an error of this class to a value, one handler per code —
the equivalent of Rust's match on an error enum.
Exhaustiveness is keyed on the value's static type, not the class's
full enum: an error typed XError<A | B> (or XError<A> | XError<B>)
requires handlers for exactly A and B. When upstream widens a
function's error union with a new code, every match on it without
else fails to compile, naming exactly the missing code.
Each handler receives the error with code and info narrowed to its
branch (info per-code requires the info-map type parameter on the
class). Add an else handler to cover any subset of codes instead;
else receives the un-narrowed error.
This is a static method (XError.match(e, ...), not e.match(...))
because distributed unions like XError<A> | XError<B> — the shape
produced by separate err() branches — cannot dispatch a generic
instance method. Calling it on the class also rejects values of other
error classes, whose numeric codes would otherwise collide.
The union of the handlers' return types.
When no handler matches at runtime — only possible when
e's static type lies (e.g. a stale build or an unchecked cast).
declare const e: ParseError<ParseErrorCode.EMPTY_INPUT | ParseErrorCode.BAD_TOKEN>
// exhaustive: every code in the value's type is required
const msg = ParseError.match(e, {
[ParseErrorCode.EMPTY_INPUT]: () => 'nothing to parse',
[ParseErrorCode.BAD_TOKEN]: (e) => `bad token ${e.info.token}`,
})
// partial: any subset plus `else`
const msg2 = ParseError.match(e, {
[ParseErrorCode.BAD_TOKEN]: (e) => `bad token ${e.info.token}`,
else: (e) => e.message,
})
// recovery inside orElse: handlers that keep a code return err(e) with e
// narrowed to that code, so recovered codes are ERASED from the union
res.orElse((e) => ParseError.match(e, {
[ParseErrorCode.EMPTY_INPUT]: () => ok([]),
[ParseErrorCode.BAD_TOKEN]: (e) => err(e), // e: ParseError<BAD_TOKEN>
})) // Result<Item[], ParseError<ParseErrorCode.BAD_TOKEN>>
// (`else` receives the un-narrowed error, so erasure needs the exhaustive form)
Exhaustively map an error of this class to a value, one handler per code —
the equivalent of Rust's match on an error enum.
Exhaustiveness is keyed on the value's static type, not the class's
full enum: an error typed XError<A | B> (or XError<A> | XError<B>)
requires handlers for exactly A and B. When upstream widens a
function's error union with a new code, every match on it without
else fails to compile, naming exactly the missing code.
Each handler receives the error with code and info narrowed to its
branch (info per-code requires the info-map type parameter on the
class). Add an else handler to cover any subset of codes instead;
else receives the un-narrowed error.
This is a static method (XError.match(e, ...), not e.match(...))
because distributed unions like XError<A> | XError<B> — the shape
produced by separate err() branches — cannot dispatch a generic
instance method. Calling it on the class also rejects values of other
error classes, whose numeric codes would otherwise collide.
The union of the handlers' return types.
When no handler matches at runtime — only possible when
e's static type lies (e.g. a stale build or an unchecked cast).
declare const e: ParseError<ParseErrorCode.EMPTY_INPUT | ParseErrorCode.BAD_TOKEN>
// exhaustive: every code in the value's type is required
const msg = ParseError.match(e, {
[ParseErrorCode.EMPTY_INPUT]: () => 'nothing to parse',
[ParseErrorCode.BAD_TOKEN]: (e) => `bad token ${e.info.token}`,
})
// partial: any subset plus `else`
const msg2 = ParseError.match(e, {
[ParseErrorCode.BAD_TOKEN]: (e) => `bad token ${e.info.token}`,
else: (e) => e.message,
})
// recovery inside orElse: handlers that keep a code return err(e) with e
// narrowed to that code, so recovered codes are ERASED from the union
res.orElse((e) => ParseError.match(e, {
[ParseErrorCode.EMPTY_INPUT]: () => ok([]),
[ParseErrorCode.BAD_TOKEN]: (e) => err(e), // e: ParseError<BAD_TOKEN>
})) // Result<Item[], ParseError<ParseErrorCode.BAD_TOKEN>>
// (`else` receives the un-narrowed error, so erasure needs the exhaustive form)
StaticprepareStatictryConvenience boundary: catch throws and return Result / AsyncResult.
Foreign failures land in Err via fromAny (often UnexpectedError at first).
Refine with mapErr / fromAny, then result.panic on remaining
UnexpectedError inside your package — do not export it to downstream callers.
Convenience boundary: catch throws and return Result / AsyncResult.
Foreign failures land in Err via fromAny (often UnexpectedError at first).
Refine with mapErr / fromAny, then result.panic on remaining
UnexpectedError inside your package — do not export it to downstream callers.
StatictryThe async part of try. Just use try instead.
StatictryThe sync part of try. Just use try instead.
Base class for expected (typed) errors — the
Ein exportedResult<T, E>.Subclass with a numeric error-code enum. Callers handle these explicitly; unwrapping a
TypedErrorusually means the call site wrongly assumed success.The optional second type parameter maps each code to its
infopayload. With it,infois typed per code (in is, match, and the constructor — which requiresinfoexactly when the map entry is notundefined-able), and the subclass needs nodeclare infoor constructor override: