dar*_*ong 57 javascript typescript
我试图抛出一个自定义错误,我的"CustomError"类名称打印在控制台而不是"错误",但没有成功:
class CustomError extends Error {
constructor(message: string) {
super(`Lorem "${message}" ipsum dolor.`);
this.name = 'CustomError';
}
}
throw new CustomError('foo');
Run Code Online (Sandbox Code Playgroud)
输出是Uncaught Error: Lorem "foo" ipsum dolor
.
我的期望:Uncaught CustomError: Lorem "foo" ipsum dolor
.
我想知道是否只能使用TS来完成(没有搞乱JS原型)?
Vid*_*dar 56
您使用的是打字稿版本2.1,并转换为ES5吗?请查看重大更改页面的此部分,以了解可能的问题和解决方法:https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-和地图-MAY-不再视为工作
相关位:
作为建议,您可以在任何超级(...)调用后立即手动调整原型.
Run Code Online (Sandbox Code Playgroud)class FooError extends Error { constructor(m: string) { super(m); // Set the prototype explicitly. Object.setPrototypeOf(this, FooError.prototype); } sayHello() { return "hello " + this.message; } }
但是,FooError的任何子类都必须手动设置原型.对于不支持Object.setPrototypeOf的运行时,您可以使用
__proto__
.不幸的是,这些变通办法不适用于Internet Explorer 10及更早版本.可以手动将原型中的方法复制到实例本身(即FooError.prototype到此),但原型链本身无法修复.
Kri*_*amp 46
问题是Javascript的内置类Error
通过将要构造的对象(即this
)转换为新的不同对象来打破原型链,当您调用super
并且新对象没有预期的原型链时,即它是一个实例的Error
不是CustomError
.
使用'new.target'可以很好地解决这个问题,这是自TypesScript 2.2以来支持的,请看这里:https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html
class CustomError extends Error {
constructor(message?: string) {
// 'Error' breaks prototype chain here
super(message);
// restore prototype chain
const actualProto = new.target.prototype;
if (Object.setPrototypeOf) { Object.setPrototypeOf(this, actualProto); }
else { this.__proto__ = actualProto; }
}
}
Run Code Online (Sandbox Code Playgroud)
使用new.target
的优势在于您无需对原型进行硬编码,就像此处提出的其他一些答案一样.这再次具有以下优点:继承的类CustomError
将自动获得正确的原型链.
如果你要对原型进行硬编码(例如Object.setPrototype(this, CustomError.prototype)
),CustomError
它本身就会有一个工作原型链,但是任何继承的类CustomError
都会被破坏,例如a的实例class VeryCustomError < CustomError
不会instanceof VeryCustomError
像预期的那样,而只是instanceof CustomError
.
另见:https://github.com/Microsoft/TypeScript/issues/13965#issuecomment-278570200
Gra*_*fus 15
从 TypeScript 2.2 开始,它可以通过new.target.prototype
.
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#example
class CustomError extends Error {
constructor(message?: string) {
super(message); // 'Error' breaks prototype chain here
this.name = 'CustomError';
Object.setPrototypeOf(this, new.target.prototype); // restore prototype chain
}
}
Run Code Online (Sandbox Code Playgroud)
T.J*_*der 10
它在ES2015(https://jsfiddle.net/x40n2gyr/)中正常工作.最有可能的问题是,TypeScript编译器正在转换为ES5,并且Error
仅使用ES5功能无法正确子类化; 它只能使用ES2015及以上功能正确地进行子类化(class
或者,更加模糊不清Reflect.construct
).这是因为,当你调用Error
一个函数(而不是通过new
或在ES2015,super
或Reflect.construct
),它忽略this
并创建一个新的 Error
.
你可能不得不忍受不完美的输出,直到你可以瞄准ES2015或更高......
小智 10
我实际上从未在 SO 上发过帖子,但我的团队正在开发一个 TypeScript 项目,我们需要创建许多自定义错误类,同时还针对 es5。在每个错误类别中执行建议的修复将是非常乏味的。extend
但我们发现,通过创建一个主要的自定义错误类,并将其余错误置于该类中,我们能够对所有后续错误类产生下游影响。在该主错误类内部,我们执行了以下操作以产生更新原型的下游效果:
class MainErrorClass extends Error {
constructor() {
super()
Object.setPrototypeOf(this, new.target.prototype)
}
}
class SomeNewError extends MainErrorClass {}
...
Run Code Online (Sandbox Code Playgroud)
使用new.target.prototype
是更新所有继承错误类而无需更新每个错误类的构造函数的关键。
只是希望这能在未来避免其他人的头痛!
几天前我在打字稿项目中遇到了同样的问题.为了使它工作,我使用仅使用vanilla js的MDN实现.所以你的错误看起来像下面这样:
function CustomError(message) {
this.name = 'CustomError';
this.message = message || 'Default Message';
this.stack = (new Error()).stack;
}
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;
throw new CustomError('foo');
Run Code Online (Sandbox Code Playgroud)
它似乎不适用于SO代码片段,但它在chrome控制台和我的打字稿项目中有效: