如何在TypeScript中扩展宿主对象(例如,错误)

Mar*_*eld 39 inheritance typescript

我想将宿主对象扩展Error为自定义UploadError类.编译时,以下示例失败:

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

    getCode(): number {
        return this.code;
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行TypeScript编译器时,tsc我收到以下错误:

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

它似乎Error被定义为一个接口.如果有人知道实现的名称是什么,它会让我很开心:-)

更新:我想使用Typescripts继承而非原型继承,就像我目前用来解决这个问题:

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;
}
Run Code Online (Sandbox Code Playgroud)

Aid*_*api 33

TypeScript 1.6更新:

现在可以直接从Error类扩展,我原来的答案中的代码仍然有效,但不再需要了export declare class Error.

原始答案:

这里的大多数答案都不符合我的要求.自0.9.5以来,最初接受的答案不再编译,并且具有重复的标识符异常.并且它们中没有一个真正有堆栈跟踪(JavaScript问题,而不是TypeScript).

对我来说,更优雅的解决方案是:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以用它做什么:

  • new Exception("msg") instanceof Error == true
  • class SpecificException extends Exception
  • catch (e) { console.log(e.stack); }

我发现的唯一限制是你必须在模块中声明它,并且不能使它们全局化.对我来说,这不是一个问题,因为我认为一个模块有助于结构化,并且它们存在于我所做的任何应用程序中.

你可以做的一个改进是从堆栈跟踪中删除你的自定义代码,我个人认为堆栈跟踪只适用于开发人员的眼睛,他们知道在哪里看,所以对我来说没什么大不了的.


Dmi*_*try 22

注意Typescript 2.1中的新变化 - 链接

因此,您可以扩展Error类,但作为建议,您需要在任何超级(...)调用后立即手动调整原型:

class FooError extends Error {
    constructor(m: string) {
        super(m);

        // Set the prototype explicitly.
        Object.setPrototypeOf(this, FooError.prototype);
    }

    sayHello() {
        return "hello " + this.message;
    }
}
Run Code Online (Sandbox Code Playgroud)


Fen*_*ton 10

更新

TypeScript 1.6带来了扩展本机类型的能力,所以当它落地时你应该可以使用

class UploadError extends Error {
    //... calls to super and all that jazz
}
Run Code Online (Sandbox Code Playgroud)

原始答案

您可以在TypeScript中实现错误接口,但super由于您没有使用继承,因此不会授予您访问权限:

class UploadError implements Error {
    public name = "CustomError";

    constructor (public message: string, private code: number){

    }
}

throw new UploadError ("Something went wrong!", 123);
Run Code Online (Sandbox Code Playgroud)


小智 10

我发现以下方法有效:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

生成的脚本如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,这会产生编译错误:错误TS2000:重复标识符'ErrorClass'. (18认同)

tan*_*y_k 6

现在可以扩展Error类版本1.6.请参阅 请求中的pull request 允许表达式扩展子句https://github.com/Microsoft/TypeScript/pull/3516并且问题无法扩展内置类型 https://github.com/Microsoft/TypeScript/issues/1168

请注意,tsc不会再抱怨,但编辑器/ IDE将会更新.