denomod / user_error

UserError is a base class that makes JavaScript/TypeScript errors a lot more useful.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

user_error

tag Build Status license

UserError is a base class that makes JavaScript errors a lot more useful. It gives you:

  • An Error subclass that actually works
  • Support for checking error types using instanceof
  • A correct name property on error objects
  • Cleaner stack traces

Usage

import UserError from "https://deno.land/x/user_error/mod.ts";

class MyError extends UserError {
  constructor(message: string) {
    super(message);
  }
}

Rationale

To see the problems UserError solves for you, let's try to subclass Error directly and see what happens.

class MyError extends Error {
  constructor(message: string) {
    super(message);
  }
}

const boom = (): never => {
  throw new MyError("boom!");
};

try {
  boom();
} catch (error) {
  error instanceof Error; // true  (correct)
  error instanceof MyError; // false (wrong, should be true)
  error.name; // Error (wrong, should be MyError)
}

In this example, subclassing Error is useless; we can't really differentiate an instance of MyError from any other Error in the system. This inability to subclass Error has led to a number of other workarounds, most often adding some kind of code property to error objects, so you end up doing stuff like this:

if (error.code === SomeErrorCode)
  // ...

In addition to this problem, errors created in this way include extra noise in their stack trace:

Error: boom!                              << should be "MyError: boom!"
    at MyError.Error (native)             << noise
    at new MyError (test.js:3:7)          << noise
    at boom (test.js:10:9)
    at Object.<anonymous> (test.js:14:3)

UserError aims to fix these problems. Now, when we run the example it looks like this:

import UserError from "https://deno.land/x/user_error/mod.ts";

class MyError extends UserError {
  constructor(message: string) {
    super(message);
  }
}

const boom = (): never => {
  throw new MyError("boom!");
};

try {
  boom();
} catch (error) {
  error instanceof Error; // true
  error instanceof MyError; // true
  error.name; // MyError
}

Since both instanceof work and the name property is setup correctly, we can do either

if (error instanceof MyError)
  // ...

or

if (error.name === 'MyError')
  // ...

instead of duck-typing with a custom property. Additionally, the stack trace doesn't contain unnecessary entries:

MyError: boom!
    at boom (test.js:10:9)
    at Object.<anonymous> (test.js:14:3)

License

user_error is released under the MIT License. See the bundled LICENSE file for details.

Thanks

Heavily inspired by mjackson/usererror.

About

UserError is a base class that makes JavaScript/TypeScript errors a lot more useful.

License:MIT License


Languages

Language:TypeScript 100.0%