TypeScript中的自定义错误类

Kub*_*a T 43 error-handling inheritance typescript

我想在TypeScript中创建自己的错误类,扩展核心Error以提供更好的错误处理和自定义报告.例如,我想创建一个HttpRequestError带有url,response和body的类传递给它的构造函数,该函数响应Http请求到http://example.com失败,状态代码为500,并显示消息:出错并且堆栈跟踪正确.

如何在TypeScript中扩展核心Error类?我已经在SO中找到了帖子:如何在TypeScript中扩展宿主对象(例如,错误),但这个解决方案对我不起作用.我使用TypeScript 1.5.3

有任何想法吗?

ziv*_*ziv 91

TypeScript 2.1在扩展内置插件(如Error)方面有重大变化.

TypeScript中断更改文档

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)

然后你可以使用:

let error = new FooError("msg");
if(error instanceof FooError){
   console.log(error.sayHello();
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么我们需要添加`Object.setPrototypeOf(this,FooError.prototype);`? (19认同)
  • 值得一提的是,需要在任何`super(...)`调用之后立即调用`Object.setPrototypeOf`. (9认同)
  • @Searene 如果您单击“TypeScript 重大更改文档”链接,它会解释原因。 (3认同)
  • 该链接不再有效。 (3认同)
  • 我需要确保`tsconfig.json`具有`“ target”:“ es6”`。 (2认同)
  • 注意 Object.setPrototypeOf https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf (2认同)

tho*_*epo 18

直到1.6滚动,我才刚刚开始自己​​的可扩展课程.

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


Pet*_*ter 16

对于 Typescript 3.7.5,此代码提供了一个自定义错误类,该类也捕获了正确的堆栈信息。注意instanceof不起作用,所以我name改用

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

还有一些其他的选择原因讨论


Ben*_*uer 15

我正在使用TypeScript 1.8,这就是我使用自定义错误类的方法:

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

MyApp.ts

import UnexpectedInput from "./UnexpectedInput";

...

throw new UnexpectedInput(UnexpectedInput.UNSUPPORTED_TYPE);
Run Code Online (Sandbox Code Playgroud)

对于早于1.8的TypeScript版本,您需要声明Error:

export declare class Error {
  public message: string;
  public name: string;
  public stack: string;
  constructor(message?: string);
}
Run Code Online (Sandbox Code Playgroud)

  • 我不明白为什么这首先是必要的:`this.stack =(<any> new Error()).stack;`应该从Error类继承,是吗? (4认同)
  • 你应该小心这种方法。我想我读到调用 stack 属性是昂贵的,应该在您的代码中避免。我认为您可能会为自定义错误增加大量开销。来自文档“访问 error.stack 属性时延迟生成表示堆栈跟踪的字符串。” (2认同)

j1n*_*3l0 14

这在当前最新版本的 typescript (4.7.3) 中似乎不是问题:

import { expect } from 'chai';
import { describe } from 'mocha';

class MyError extends Error {}

describe('Custom error class "MyError"', () => {
  it('should be an instance of "MyError"', () => {
    try {
      throw new MyError();
    } catch (e) {
      expect(e).to.be.an.instanceOf(MyError);
    }
  });
});
Run Code Online (Sandbox Code Playgroud)

我不确定哪个版本改变了行为,但此测试在 2.1 上失败。


Hug*_*sse 6

https://www.npmjs.com/package/ts-custom-error有一个简洁的库

ts-custom-error 允许您非常轻松地创建错误自定义错误:

import { CustomError } from 'ts-custom-error'
 
class HttpError extends CustomError {
    public constructor(
        public code: number,
        message?: string,
    ) {
        super(message)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

new HttpError(404, 'Not found')
Run Code Online (Sandbox Code Playgroud)