Create multiple error types.
Features
- Create custom error types
- Automatically separate known and unknown errors
- Unknown errors indicate where to report bugs
- Set properties on individual errors, or on all errors of the same type
Example
Create custom error types.
// `error.js`
import createErrorTypes from 'create-error-types'
export const { InputError, AuthError, DatabaseError, errorHandler } =
createErrorTypes(['InputError', 'AuthError', 'DatabaseError'])
Wrap the main function with the error handler.
import { errorHandler } from './error.js'
export const main = async function (filePath) {
try {
return await readContents(filePath)
} catch (error) {
throw errorHandler(error)
}
}
Throw/re-throw errors.
import { InputError } from './error.js'
const readContents = async function (filePath) {
try {
return await readFile(filePath)
} catch (cause) {
throw new InputError(`Could not read ${filePath}`, { cause })
}
}
Install
npm install create-error-types
This package is an ES module and must be loaded using
an import
or import()
statement,
not require()
.
API
createErrorTypes(errorNames, options?)
errorNames
: string[]
options
object
Return value: object
Creates custom error types.
Return value
Any error type
Type: CustomErrorType
Any error name passed as argument is returned as an error type.
errorHandler
Type: (anyException) => CustomError
Error handler that should wrap each main function.
Options
bugsUrl
Type: string | URL | ((error: Error) => string | URL | void)
URL where users should report unknown errors.
onCreate
Type: (error, parameters) => void
Called on any
new CustomErrorType('message', parameters)
. Can be
used to customize error parameters or set
error type properties. By default, any parameters
are set as error properties.
Usage
Setup
Create custom error types
// error.js
import createErrorTypes from 'create-error-types'
export const { InputError, AuthError, DatabaseError, errorHandler } =
createErrorTypes(['InputError', 'AuthError', 'DatabaseError'])
Error handler
Each main function should be wrapped with the errorHandler()
.
import { errorHandler } from './error.js'
export const main = async function (filePath) {
try {
return await readContents(filePath)
} catch (error) {
// `errorHandler()` returns `error`, so `throw` must be used
throw errorHandler(error)
}
}
Throw errors
import { InputError } from './error.js'
const validateFilePath = function (filePath) {
if (filePath === '') {
throw new InputError('Missing file path.')
}
}
Error types
Test error type
Once errorHandler()
has been applied, the error type can be
checked by its name
. Libraries should document their possible error names, but
do not need to export
their error types.
if (error.name === 'InputError') {
// ...
} else if (error.name === 'UnknownError') {
// ...
}
Set error type
error.cause
can be used to override the type of an inner error.
try {
throw new AuthError('Could not authenticate.')
} catch (cause) {
throw new InputError('Could not read the file.', { cause })
// Now an InputError
}
Unknown errors
All errors should use known types: the ones returned by
createErrorTypes()
. Errors with an unknown
type should be handled in try {} catch {}
and re-thrown
with a known type instead.
The errorHandler()
assigns the UnknownError
type to any
error with an unknown type.
const getUserId = function (user) {
return user.id
}
getUserId(null) // UnknownError: Cannot read properties of null (reading 'id')
Bug reports
If the bugsUrl
option is a string or URL, any
unknown error will include the following message.
createErrorTypes({ bugsUrl: 'https://github.com/my-name/my-project/issues' })
Please report this bug at: https://github.com/my-name/my-project/issues
If the bugsUrl
option is a function returning a string or URL, any error
(known or unknown) will include it, unless the return
value is undefined
.
createErrorTypes({
bugsUrl: (error) =>
error.name === 'UnknownError' || error.name === 'PluginError'
? 'https://github.com/my-name/my-project/issues'
: undefined,
})
Error properties
Set error properties
Unless the onCreate()
option is defined, any parameter is set as
an error property.
const error = new InputError('Could not read the file.', { filePath: '/path' })
console.log(error.filePath) // '/path'
Customize error parameters
The onCreate()
option can be used to validate and transform error
parameters
.
createErrorTypes({
onCreate(error, parameters) {
const { filePath } = parameters
if (typeof filePath !== 'string') {
throw new Error('filePath must be a string.')
}
const hasFilePath = filePath !== undefined
Object.assign(error, { filePath, hasFilePath })
},
})
const error = new InputError('Could not read the file.', {
filePath: '/path',
unknownParam: true,
})
console.log(error.filePath) // '/path'
console.log(error.hasFilePath) // true
console.log(error.unknownParam) // undefined
Type-specific logic
The onCreate()
option can trigger error type-specific logic.
createErrorTypes({
onCreate(error, parameters) {
onCreateError[error.name](error, parameters)
},
})
const onCreateError = {
InputError(error, parameters) {
// ...
},
AuthError(error, parameters) {
// ...
},
// ...
}
Error type properties
The onCreate()
option can be used to set properties on all
instances of a given error type.
createErrorTypes({
onCreate(error, parameters) {
Object.assign(error, parameters, ERROR_PROPS[error.name])
},
})
const ERROR_PROPS = {
InputError: { isUser: true },
AuthError: { isUser: true },
DatabaseError: { isUser: false },
}
const error = new InputError('Could not read the file.')
console.log(error.isUser) // true
Related projects
-
modern-errors
: Handle errors like it's 2022 🔮 -
error-type
: Create custom error types -
error-serializer
: Convert errors to/from plain objects -
normalize-exception
: Normalize exceptions/errors -
merge-error-cause
: Merge an error with itscause
-
error-cause-polyfill
: Polyfillerror.cause
-
handle-cli-error
: 💣 Error handler for CLI applications 💥 -
log-process-errors
: Show some ❤ to Node.js process errors
Support
For any question, don't hesitate to submit an issue on GitHub.
Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.
Contributing
This project was made with ❤️. The simplest way to give back is by starring and sharing it online.
If the documentation is unclear or has a typo, please click on the page's Edit
button (pencil icon) and suggest a correction.
If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!