Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I extend a host object (e.g. Error) in TypeScript

I would like to extend the host object Error to a custom UploadError class. The following example fails when I compile:

class UploadError extends Error {     constructor(message: string, private code: number) {         super(message);     }      getCode(): number {         return this.code;     } } 

When I run the TypeScript compiler tsc I get the following error:

UploadError.ts(1,0): A export class may only extend other classes, Error is an interface. 

It seems Error is defined as an interface. If anyone knows what the name of the implementation is it would make me very happy :-)

Update: I want to use Typescripts inheritance not prototypical inheritance like I currently employ to hack around this:

function UploadError (message: string, code: number) {     this.message = message;     this.code = code; }  UploadError.prototype = new Error();  UploadError.prototype.constructor = UploadError;  UploadError.prototype.getCode = (): number => {     return this.code; } 
like image 725
Marijn Huizendveld Avatar asked Oct 16 '12 13:10

Marijn Huizendveld


People also ask

How do I use TypeScript extends?

Just like object-oriented languages such as Java and C#, TypeScript classes can be extended to create new classes with inheritance, using the keyword extends . In the above example, the Employee class extends the Person class using extends keyword.

What does Extends mean in TypeScript?

extends means it gets all from its parent. implements in this case it's almost like implementing an interface. A child object can pretend that it is its parent... but it does not get any implementation.

How do you throw an exception in TypeScript?

To declare a function that throws an error, set its return type to never . The never type is used for functions that never return a value, in other words functions that throw an exception or terminate execution of the program.


2 Answers

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.

like image 144
Aidiakapi Avatar answered Sep 28 '22 10:09

Aidiakapi


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;     } } 
like image 33
Dmitry Avatar answered Sep 28 '22 08:09

Dmitry