Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

b12-archive/tiny-error

Repository files navigation

Coveralls – test coverage Travis – build status David – status of dependencies Code style: airbnb

tiny-error

Super-light error objects.
Inspired by go.



lightweight

I’m no expert with go, but I have heard three things:

  • go has no heavy try/catch mechanism. We all know that try/catch in JS is slowish – and you can do well without it.

  • go does have a thing called panic. You use it when you encounter an error which you absolutely can’t recover from. It just crashes the program and displays a readable message to the developer or user.

  • go has no heavy stack traces. That’s mental overhead for the user. If you ask me, I don’t like stack traces with umpty-ump calls to dig through. (If you’ve ever used node streams or RxJS, you know what I mean.) I really prefer a descriptive overview of what went wrong, why it went wrong, what to do next and a read-up link.

Since go programmers like it so, why not try lightweight errors in JavaScript?

Installation

$ npm install tiny-error

Demo

Native:

throw new Error('Something went wrong.');
//» Error: Something went wrong.
//»     at repl:1:7
//»     at REPLServer.self.eval (repl.js:110:21)
//»     at repl.js:249:20
//»     at REPLServer.self.eval (repl.js:122:7)
//»     at Interface.<anonymous> (repl.js:239:12)
//»     at Interface.emit (events.js:95:17)
//»     at Interface._onLine (readline.js:203:10)
//»     at Interface._line (readline.js:532:8)
//»     at Interface._ttyWrite (readline.js:761:14)
//»     at ReadStream.onkeypress (readline.js:100:10)

Tiny:

throw tinyError('Something went wrong.');
//» Error: Something went wrong.

Prefer to stay tiny? Then read on.

Usage

tiny-error is a maker function*. It creates a new object based on Error.prototype, but doesn’t invoke the Error constructor directly – thus saving us from creating a stack trace.

It’s a simple idea – so usage is simple:

const tinyError = require('tiny-error');

tinyError('Oops!');
//» { [Error: Oops!] message: 'Oops!' }

tinyError({message: 'Oops!', myErrorCode: 7});
//» { [Error: Oops!] message: 'Oops!', myErrorCode: 7 }

throw tinyError('Oops!');
//» Error: Oops!            (Output depends on how your engine presents errors.)

There is still power behind this simplicity. Just enough to keep it easy to use but still flexible:

throw tinyError({
  prefix: '[my library] ',
  message: 'Curses! Try once more.',
});
//» Error: [my library] Curses! Try once more.

const myError = tinyError({prefix: '[my library] '});
throw myError('Curses! Try once more.');
//» Error: [my library] Curses! Try once more.

throw myError('Oh no. Not again!');
//» Error: [my library] Oh no. Not again!

* maker function – a term I coined together for a function that creates an object. Not an instance of a class (that’s a factory). Not an instance of a specific class (constructor). Just an object. If there is another word for that, great! Tell me in an issue please.

API

tinyError(message)
  → {Error}

A shortcut to tinyError({message: message}).

Parameters:

  • {String} message

tinyError(args)
  → {Function} tinyErrorCurried

tinyError(args)
  → {Error}

An error maker.

We return an {Error} if args contains a {String} args.message. Otherwise we return a curried function. So these are equivalent:

tinyError({
  prefix: '[my library] ',
  myCode: 2,
  prototype: TypeError.prototype,
  message: '`something` should be a number.',
});


const myError = tinyError({prefix: '[my library] '})
myError({
  myCode: 2,
  prototype: TypeError.prototype,
  message: '`something` should be a number.',
});


const argumentError = myError({myCode: 2, prototype: TypeError.prototype});
argumentError('`something` should be a number.');

All args are just copied to the target object – except three special-cased:

Parameters:

  • {Function} args.prefix
    we’ll prepend it to the message

  • {Function} args.suffix
    we’ll append it to the message

  • {Function} args.prototype
    will be used as prototype instead of Error.prototype

Keep in mind that some properties like message and name will be treated specially by Error.prototype.

License

MIT © Studio B12 GmbH