Skip to content

Instantly share code, notes, and snippets.

@alexsasharegan
Created January 3, 2020 17:51
Show Gist options
  • Save alexsasharegan/557c897658175aaf11e0d4330478465e to your computer and use it in GitHub Desktop.
Save alexsasharegan/557c897658175aaf11e0d4330478465e to your computer and use it in GitHub Desktop.
Wrap errors using a linked list. Error burritos 🌯
export class WrappedError<ErrKind = any> extends Error implements Iterable<WrappedError | ErrKind> {
previous: ErrKind | null = null;
guid: Guid;
constructor(message: string, previous?: ErrKind) {
super(message);
// We update the error's name to distinguish it from the base Error.
this.name = this.constructor.name;
this.guid = `<${this.name}:empty>`;
// We add our reference to the original error value (if provided).
if (previous != null) {
this.previous = previous;
}
}
/**
* Iterate through the error stack from head to tail (most recent to root error).
*/
*[Symbol.iterator](): Iterator<WrappedError | ErrKind> {
let err: any = this;
for (; err instanceof WrappedError; err = err.previous) {
yield err;
}
if (err != null) {
yield err;
}
}
*messageValues(): IterableIterator<string> {
for (let error of this) {
if (error instanceof Error) {
yield error.message;
} else {
yield String(error);
}
}
}
/**
* The original error value.
*/
get root(): WrappedError<null> | ErrKind {
// Base case, no child === this instance is root
if (this.previous == null) {
return this as any;
}
// When the child is another node, compute recursively
if (this.previous instanceof WrappedError) {
return this.previous.root;
}
// This instance wraps the original error
return this.previous;
}
/**
* An array of all the stringified, non-nullable errors.
*/
get spans(): string[] {
return Array.from(this.messageValues());
}
/**
* The unique identifier should use a short, randomly generated id string.
* Best practice is to prefix that id with a namespace and then a separator.
* Prefixes should follow this format:
*
* - Components: `<ComponentName>::$guid`
* - Classes: `Classname::$guid`
* - General file: `filename::$guid`
* - Special Cases: `STATIC_NAME::$guid`
*/
setGuid(guid: Guid): this {
this.guid = guid;
return this;
}
static extractGuids(e: WrappedError) {
return Array.from(e, (value) => {
if (value instanceof WrappedError) {
return value.guid;
}
return "<empty>";
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment