我想将主机对象Error
扩展为自定义UploadError
类。编译时,以下示例失败:
class UploadError extends Error {
constructor(message: string, private code: number) {
super(message);
}
getCode(): number {
return this.code;
}
}
当我运行TypeScript编译器tsc
时,我收到以下错误:
UploadError.ts(1,0): A export class may only extend other classes, Error is an interface.
似乎Error
被定义为接口。如果有人知道实现的名称是什么,它会让我非常高兴: - )
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;
}
答案 0 :(得分:33)
现在可以直接从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;
}
}
}
你可以用它做什么:
new Exception("msg") instanceof Error == true
class SpecificException extends Exception
catch (e) { console.log(e.stack); }
我发现的唯一限制是你必须在一个模块中声明它,并且不能使它们全局化。对我来说这不是问题,因为我认为一个模块有助于结构化,他们在我的任何申请中都有。
你可以做的一个改进是从堆栈跟踪中删除你的自定义代码,我个人认为堆栈跟踪仅供开发人员使用,他们知道在哪里看,所以对我来说没什么大不了的。
答案 1 :(得分:21)
关注Typescript 2.1中的新变化 - link
所以你可以扩展Error类,但作为建议,你需要在任何超级(...)调用后立即手动调整原型:
private DataTable CreateResultDataTable()
{
DataTable Result = new DataTable();
foreach (DataGridViewRow row in dataGridView1.Rows)
{
var cell = row.Cells[1].Value;
if(cell!=null){
Result.Columns.Add(cell.ToString()); // why is Value null here ??
}
}
return Result;
}
答案 2 :(得分:10)
TypeScript 1.6带来了扩展原生类型的能力,所以当它落地时你应该能够使用
class UploadError extends Error {
//... calls to super and all that jazz
}
您可以在TypeScript中实现错误界面,但由于您没有使用继承,因此无法访问super
:
class UploadError implements Error {
public name = "CustomError";
constructor (public message: string, private code: number){
}
}
throw new UploadError ("Something went wrong!", 123);
答案 3 :(得分: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);
}
}
生成的脚本如下所示:
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);
答案 4 :(得分:6)
现在可以扩展Error
类版本1.6。请参阅拉取请求允许在类扩展子句中使用表达式 https://github.com/Microsoft/TypeScript/pull/3516并发出无法扩展内置类型 https://github.com/Microsoft/TypeScript/issues/1168
请注意,tsc
不会再抱怨,但您的编辑器/ IDE将会更新。
答案 5 :(得分:1)
我知道答案已被接受,解决方案肯定令人印象深刻,但我真的不希望我的项目中有大量代码只是为了例外。
在TypeScript以某种方式在语言级别获得正确的异常之前,由于Error的扩展非常麻烦,我现在使用以下非常简单的解决方案:
class MyError {
constructor(error: Error) {
error.name = this['constructor'].name;
error['type'] = this; // for type-checking in exception-handlers
return error;
}
}
throw new MyError(new Error('aw snap!'));
现在,我的错误类型实际上是类 - 您可以扩展它们,并且当抛出未处理的错误时,您将在控制台上看到正确的类名;但我的错误对象不是这些类的实例:构造函数不返回MyError的实例,它只是将它自己的名称应用于传递给它的Error实例。
这也提供了一个简单的解决方法,用于在构造它时产生它的堆栈跟踪错误,而不是在你抛出它的位置 - 因为构造函数签名强迫你建立一个真正的&#34;错误实例。
如果您需要检查异常处理程序中的异常类型,请抓取['type']
属性并使用instanceof
进行比较:
try {
// something throws new MyError(new Error('aw snap!'))
} catch (error) {
console.log(error['type'] instanceof MyError); // => true
}
它并不理想,但它很简单且有效。
请注意,如果扩展MyError,则需要每次都实现构造函数并添加return super(...)
,因为TypeScript生成的默认构造函数不期望构造函数使用return语句。它确实允许他们。
答案 6 :(得分:1)
使用TypeScript 0.8.3时,Ron Buckton的解决方案对我有用,但它不能在TypeScript 0.9.5中编译。 TypeScript生成编译错误:重复标识符'ErrorClass'。我已更改代码以使其再次运行:
declare class ErrorClass {
public name: string;
public message: string;
constructor(message?: string);
}
// Move following line to a JavaScript
// (not TypeScript) file.
// var ErrorClass = Error;
class MyError extends ErrorClass {
public name = "MyError";
constructor (public message?: string) {
super(message);
}
}
答案 7 :(得分:1)
我找到了解决方案。不好,但也工作...使用eval()JS函数忽略TypeScript检查。
declare class ErrorClass implements Error {
public name: string;
public message: string;
constructor(message?: string);
}
eval('ErrorClass = Error');
export = Exception;
class Exception extends ErrorClass implements Error { ... }
答案 8 :(得分:1)
我使用的是TypeScript 1.8,但这可能适用于早期版本:
class MyError extends Error {
static name: string;
constructor(public message?: string, public extra?: number) {
super(message);
Error.captureStackTrace(this, MyError);
this.name = (this as any).constructor.name; // OR (<any>this).constructor.name;
}
};
请注意,您必须安装node
类型才能使用Error.captureStackTrace
。
答案 9 :(得分:1)
扩展接口是记录here的重大变化。
解决方案:在构造函数中手动更改原型。
class MyError extends Error {
constructor(m: string) {
super(m);
// Set the prototype explicitly. If you skip this, iinstanceof will not work :-(
(<any>this).__proto__ = MyError.prototype;
}
}
console.log("Instance of works now: "+(new MyError("my error") instanceof MyError));
答案 10 :(得分:0)
您可以使用原型添加功能和属性:
interface Error {
code: number;
getCode(): number;
}
Error.prototype.code = 1;
Error.prototype.getCode = function () {
return this.code;
}
var myError = new Error();
console.log("Code: " + myError.getCode());
使用node.js
运行时,会产生以下输出:
Code: 1
错误在lib.d.ts
中定义如下:
interface Error {
name: string;
message: string;
}
declare var Error: {
new (message?: string): Error;
(message?: string): Error;
prototype: Error;
}
除此之外,我只看到明确的解决方案来定义扩展Error
的自己的界面:
interface MyErrorInterface extends Error {
code: number;
getCode(): number;
}
class MyError implements MyErrorInterface {
code : number;
name : string;
message : string;
constructor(code: number, name? : string, message? : string) {
this.code = code;
this.name = name;
this.message = message;
}
getCode(): number {
return this.code;
}
}
var myError = new MyError(1);
console.log("Code: " + myError.getCode());