How do I extend a host object (e.g. Error) in TypeScript
Update for TypeScript 1.6:
It's now possible to directly extend from the Error
class, the code in my original answer still works, but there's no longer a need for the export declare class Error
.
Original answer:
Most of the answers here don't meet my requirements. The originally accepted answer doesn't compile anymore since 0.9.5 with a duplicate identifier exception. And non of them really have a stack trace (a JavaScript issue, not TypeScript).
For me a more elegant solution is:
module YourModule {
export declare class Error {
public name: string;
public message: string;
public stack: string;
constructor(message?: string);
}
export class Exception extends Error {
constructor(public message: string) {
super(message);
this.name = 'Exception';
this.message = message;
this.stack = (<any>new Error()).stack;
}
toString() {
return this.name + ': ' + this.message;
}
}
}
What you can do with it:
new Exception("msg") instanceof Error == true
class SpecificException extends Exception
catch (e) { console.log(e.stack); }
The only limitation I found was that you have to declare it in a module, and cannot make them global. For me this isn't an issue since I think a module helps in structuring, and they are there in any application I make.
One improvement you could make is strip your custom code from the stack trace, personally I think stacktraces are only for the eyes of developers, and they know where to look, so it's no big deal for me.
pay attention on the new changes in Typescript 2.1 - link
So you can extend the Error class but, as a recommendation, you need manually adjust the prototype immediately after any super(...) calls:
class FooError extends Error {
constructor(m: string) {
super(m);
// Set the prototype explicitly.
Object.setPrototypeOf(this, FooError.prototype);
}
sayHello() {
return "hello " + this.message;
}
}
I have found the following approach works:
declare class ErrorClass implements Error {
public name: string;
public message: string;
constructor(message?: string);
}
var ErrorClass = Error;
class MyError extends ErrorClass {
public name = "MyError";
constructor (public message?: string) {
super(message);
}
}
The generated script looks like:
var ErrorClass = Error;
var MyError = (function (_super) {
__extends(MyError, _super);
function MyError(message) {
_super.call(this, message);
this.message = message;
this.name = "MyError";
}
return MyError;
})(ErrorClass);
Update
TypeScript 1.6 is bringing the ability to extend native types, so when this lands you should be able to use
class UploadError extends Error {
//... calls to super and all that jazz
}
Original Answer
You can implement the error interface in TypeScript, but this won't give you access to super
as you aren't using inheritance:
class UploadError implements Error {
public name = "CustomError";
constructor (public message: string, private code: number){
}
}
throw new UploadError ("Something went wrong!", 123);
This is now possible to extend Error
class version 1.6. See pull request Allow expressions in class extends clauses https://github.com/Microsoft/TypeScript/pull/3516 and issue Can not extend built in types https://github.com/Microsoft/TypeScript/issues/1168
Note that tsc
won't complain anymore but your editor/IDE will until it gets updated.