You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
9.6 KiB
166 lines
9.6 KiB
10 months ago
|
# Typescript Custom Error
|
||
|
|
||
|
[](https://www.npmjs.com/package/ts-custom-error)
|
||
|
[](#automate-all-the-things)
|
||
|
[](https://opensource.org/licenses/MIT)
|
||
|
[](https://github.com/adriengibrat/ts-custom-error/actions/workflows/build.yml)
|
||
|
[](https://bettercodehub.com/results/adriengibrat/ts-custom-error)
|
||
|
[](https://github.com/adriengibrat/ts-custom-error/actions/workflows/codeql.yml)
|
||
|
[](https://codeclimate.com/github/adriengibrat/ts-custom-error/maintainability)
|
||
|
[](https://codeclimate.com/github/adriengibrat/ts-custom-error/test_coverage)
|
||
|
[](http://commitizen.github.io/cz-cli/)
|
||
|
[](https://packagephobia.now.sh/result?p=ts-custom-error)
|
||
|
[](https://bundlephobia.com/result?p=ts-custom-error)
|
||
|
|
||
|
## Extend native Error to create custom errors
|
||
|
|
||
|
`ts-custom-error` is a tiny (~500 bytes of minified & gzipped Javascript) package providing a `CustomError` class and a `customErrorFactory` function to easily extends native Error in node and evergreen browsers.
|
||
|
|
||
|
It's written in Typescript and try to offer the best development and debug experiences: bundled in Javascript with Typescript definition files, map files and bundled js files for various environments: transpiled to es5 with commonjs, module and umd exports, the umd bundle is also available minified for easy import in browsers.
|
||
|
|
||
|
## Why
|
||
|
|
||
|
Because [extending native Error in node and in browsers is tricky](https://stackoverflow.com/questions/1382107/whats-a-good-way-to-extend-error-in-javascript)
|
||
|
```js
|
||
|
class MyError extends Error {
|
||
|
constructor(m) {
|
||
|
super(m)
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
[doesn't work as expected in ES6](https://stackoverflow.com/questions/31089801/extending-error-in-javascript-with-es6-syntax-babel) and [is broken in Typescript](https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work).
|
||
|
|
||
|
### Use `CustomError` class
|
||
|
|
||
|
Simply extends and call `super` in you custom constructor.
|
||
|
|
||
|
```ts
|
||
|
import { CustomError } from 'ts-custom-error'
|
||
|
|
||
|
class HttpError extends CustomError {
|
||
|
public constructor(
|
||
|
public code: number,
|
||
|
message?: string,
|
||
|
) {
|
||
|
super(message)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
...
|
||
|
|
||
|
new HttpError(404, 'Not found')
|
||
|
```
|
||
|
You may want more advanced contructor logic and custom methods, see [examples](https://github.com/adriengibrat/ts-custom-error/tree/main/src/example)
|
||
|
|
||
|
### Use `customErrorFactory` factory
|
||
|
|
||
|
*Custom error contructor returned by the factory pass the same unit tests as Class constructor.*
|
||
|
|
||
|
Factory still allows custom logic inside constructor:
|
||
|
|
||
|
```ts
|
||
|
import { customErrorFactory } from 'ts-custom-error'
|
||
|
|
||
|
const HttpError = customErrorFactory(function HttpError (code: number, message= '') {
|
||
|
this.code = code
|
||
|
this.message = message
|
||
|
})
|
||
|
|
||
|
...
|
||
|
|
||
|
new HttpError(404, 'Not found')
|
||
|
```
|
||
|
|
||
|
Custom Error from `customErrorFactory` can:
|
||
|
- Be called as a simple function
|
||
|
```ts
|
||
|
HttpError(404, 'Not found')
|
||
|
```
|
||
|
- Extend any native Error, using the second optional argument
|
||
|
```ts
|
||
|
import { customErrorFactory } from 'ts-custom-error'
|
||
|
|
||
|
const ValidationError = customErrorFactory(function ValidationError (message= 'Invalid parameter') {
|
||
|
this.message = message
|
||
|
}, TypeError)
|
||
|
```
|
||
|
|
||
|
### Known limitations
|
||
|
|
||
|
#### Minification and transpilation mangle custom Error names.
|
||
|
Unexpected results are:
|
||
|
- Minified identifiers in place of custom Error name in Stacktrace
|
||
|
- Wrong error recognition where using errors name (bad practice) instead of `instanceof`
|
||
|
|
||
|
You may fix this behaviour by:
|
||
|
- Using [uglifyjs options](https://github.com/mishoo/UglifyJS2/blob/harmony/README.md) `--mangle 'except=["MyError"]'` (need to specify all custom error names) or `--keep_fnames` / `--keep_classnames` (nothing to specify but your bundle size will be larger)
|
||
|
- Setting explicitly error name:
|
||
|
|
||
|
```ts
|
||
|
import { CustomError } from 'ts-custom-error'
|
||
|
|
||
|
class MyError extends CustomError {
|
||
|
constructor() {
|
||
|
super()
|
||
|
// Set name explicitly as minification can mangle class names
|
||
|
Object.defineProperty(this, 'name', { value: 'MyError' })
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
```ts
|
||
|
import { customErrorFactory } from 'ts-custom-error'
|
||
|
|
||
|
const MyError = customErrorFactory(function MyError () {
|
||
|
// Set name explicitly as minification can remove function expression names
|
||
|
Object.defineProperty(this, 'name', { value: 'MyError' })
|
||
|
})
|
||
|
```
|
||
|
|
||
|
### Usefull development commands
|
||
|
|
||
|
- Watch source changes and run corresponding unit tests
|
||
|
```
|
||
|
npm start
|
||
|
```
|
||
|
|
||
|
- Run all unit tests
|
||
|
```
|
||
|
npm test
|
||
|
```
|
||
|
|
||
|
- Get coverage report
|
||
|
```
|
||
|
npm run coverage
|
||
|
```
|
||
|
|
||
|
- Format staged code and run commitizen (enforce commit message convention)
|
||
|
```
|
||
|
npm run commit
|
||
|
```
|
||
|
|
||
|
### Automate all the things
|
||
|
|
||
|
⚠️ This project is mainly a pet project and its first purpose is to be a playground for various external services and tools:
|
||
|
- opinionated code style mostly inspired from [standardjs](https://standardjs.com)
|
||
|
- automatic code formating with [prettier](https://github.com/prettier/prettier)
|
||
|
- code quality analysis by [codeclimate](https://codeclimate.com/github/adriengibrat/ts-custom-error)~~, [bithound](https://www.bithound.io/github/adriengibrat/ts-custom-error)~~, [bettercodehub](https://bettercodehub.com/results/adriengibrat/ts-custom-error) & [CodeQL](https://github.com/adriengibrat/ts-custom-error/security/code-scanning)
|
||
|
- automated continuous integration on ~~[travis](https://travis-ci.org/adriengibrat/ts-custom-error)~~ [github actions](https://github.com/adriengibrat/ts-custom-error/actions) & [Dependabot](https://github.com/adriengibrat/ts-custom-error/security/dependabot)
|
||
|
- automated semantic versioning with [changelog](CHANGELOG.md) generation and release deployment on [npm](https://www.npmjs.com/package/ts-custom-error) and [github](https://github.com/adriengibrat/ts-custom-error/releases) thanks to [semantic-release](https://github.com/semantic-release/semantic-release)
|
||
|
|
||
|
## Licence
|
||
|
|
||
|
Starting [version 3.0.0](https://github.com/adriengibrat/ts-custom-error/releases/tag/v3.0.0) this project is under [MIT licence](LICENSE), there are no code change between [version 2.2.2](https://github.com/adriengibrat/ts-custom-error/releases/tag/v2.2.2) and [version 3.0.0](https://github.com/adriengibrat/ts-custom-error/releases/tag/v3.0.0) but changing licence was considered as a breaking change. All [versions < 3.0.0](https://github.com/adriengibrat/ts-custom-error/releases) are under [WTFPL](http://www.wtfpl.net).
|
||
|
|
||
|
## Similar packages
|
||
|
|
||
|
- [](https://www.npmjs.com/package/custom-error) [custom-error](https://github.com/andrezsanchez/custom-error) provides a factory with custom name and parent error
|
||
|
- [](https://www.npmjs.com/package/custom-errors) [custom-errors](https://github.com/techjacker/custom-errors) provides a class and a factory with custom name and message, easy integration with with [express](https://github.com/expressjs/express) and (log)[https://github.com/visionmedia/log.js]
|
||
|
- [](https://www.npmjs.com/package/custom-error-generator) [custom-error-generator](https://github.com/jproulx/node-custom-error) provides a factory with custom name, default properties and a constructor (node only)
|
||
|
- [](https://www.npmjs.com/package/custom-error-instance) [custom-error-instance](https://github.com/Gi60s/custom-error-instance) provides a factory with custom name, properties and construction logic (! browser compatibility: redefine constructor name)
|
||
|
- [](https://www.npmjs.com/package/node-custom-errors) [node-custom-errors](https://github.com/axyjs/node-custom-errors) provides factories to create abstract or concrete error with default message, an optional constructor function allow more custom properties/methods (node/chrome only, because no feature detection)
|
||
|
- [](https://www.npmjs.com/package/extendable-error) [extendable-error](https://github.com/vilic/extendable-error) provides a class with clean stacktrace even in non v8 environments
|
||
|
- [](https://www.npmjs.com/package/extendable-error-class) [extendable-error-class](https://github.com/brillout/extendable-error-class) provides simple class
|
||
|
- [](https://www.npmjs.com/package/extend-error) [extend-error](https://github.com/jayyvis/extend-error) provides a factory attached to global Error object, allows custom name, code & message error
|
||
|
- [](https://www.npmjs.com/package/error-extend) [error-extend](https://github.com/tilap/error-extend) provides a factory with custom name, default code & message properties, an optional init function allow more custom properties/methods
|