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.