Custom error class in TypeScript
InheritanceError HandlingTypescriptInheritance Problem Overview
I'd like to create my own error class in TypeScript, extending core Error
to provide better error handling and customized reporting. For example, I want to create an HttpRequestError
class with url, response and body passed into its constructor, which reponds with Http request to http://example.com failed with status code 500 and message: Something went wrong and proper stack trace.
How to extend core Error class in TypeScript? I've already found post in SO: https://stackoverflow.com/questions/12915412/how-do-i-extend-a-host-object-e-g-error-in-typescript but this solution doesn't work for me. I use TypeScript 1.5.3
Any ideas?
Inheritance Solutions
Solution 1 - Inheritance
TypeScript 2.1 had a breaking changes regarding Extending built-ins like Error.
From the TypeScript breaking changes documentation
class FooError extends Error {
constructor(msg: string) {
super(msg);
// Set the prototype explicitly.
Object.setPrototypeOf(this, FooError.prototype);
}
sayHello() {
return "hello " + this.message;
}
}
Then you can use:
let error = new FooError("Something really bad went wrong");
if(error instanceof FooError){
console.log(error.sayHello());
}
Solution 2 - Inheritance
Until 1.6 rolls around, I've just been making my own extendable classes.
class BaseError {
constructor () {
Error.apply(this, arguments);
}
}
BaseError.prototype = new Error();
class HttpRequestError extends BaseError {
constructor (public status: number, public message: string) {
super();
}
}
var error = new HttpRequestError(500, 'Server Error');
console.log(
error,
// True
error instanceof HttpRequestError,
// True
error instanceof Error
);
Solution 3 - Inheritance
I am using TypeScript 1.8 and this is how I use custom error classes:
UnexpectedInput.ts
class UnexpectedInput extends Error {
public static UNSUPPORTED_TYPE: string = "Please provide a 'String', 'Uint8Array' or 'Array'.";
constructor(public message?: string) {
super(message);
this.name = "UnexpectedInput";
this.stack = (<any> new Error()).stack;
}
}
export default UnexpectedInput;
MyApp.ts
import UnexpectedInput from "./UnexpectedInput";
...
throw new UnexpectedInput(UnexpectedInput.UNSUPPORTED_TYPE);
For TypeScript versions older than 1.8, you need to declare Error
:
export declare class Error {
public message: string;
public name: string;
public stack: string;
constructor(message?: string);
}
Solution 4 - Inheritance
For Typescript 3.7.5 this code provided a custom error class that also captured the correct stack information. Note instanceof
does not work so I use name
instead
// based on https://gunargessner.com/subclassing-exception
// example usage
try {
throw new DataError('Boom')
} catch(error) {
console.log(error.name === 'DataError') // true
console.log(error instanceof DataError) // false
console.log(error instanceof Error) // true
}
class DataError {
constructor(message: string) {
const error = Error(message);
// set immutable object properties
Object.defineProperty(error, 'message', {
get() {
return message;
}
});
Object.defineProperty(error, 'name', {
get() {
return 'DataError';
}
});
// capture where error occured
Error.captureStackTrace(error, DataError);
return error;
}
}
There are some other alternatives and a discussion of the reasons.
Solution 5 - Inheritance
There is a neat library for this at https://www.npmjs.com/package/ts-custom-error
ts-custom-error
allow you to create error custom Error very easily:
import { CustomError } from 'ts-custom-error'
class HttpError extends CustomError {
public constructor(
public code: number,
message?: string,
) {
super(message)
}
}
usage:
new HttpError(404, 'Not found')