ES6将某些本机对象指定为可子类化,例如Object,Boolean,Error,Map,Promise等。 这些构造在lib.d.ts中建模的方式使子类化成为不可能,因为它们被定义为一对var和一个接口。
根据ES6规范第19.5.1节:
Error构造函数设计为可子类化的。 它可以用作类声明的extends子句的值。 打算继承指定的Error行为的子类构造函数应包括对Error构造函数的超级调用,以初始化子类实例。
当前,这将导致“一个类只能扩展另一个类”错误:
class NotImplementedError extends Error {
constructor() {
super("Not Implemented");
}
}
对于任何公开本来可以归类的函数的js库,这都是一个普遍的问题。 如果我的库导出了Foo构造函数并希望接收Foo的子类实例(而不仅仅是实现Foo式接口的对象),则目前尚无办法允许这样做。
我想说
class Error;
这样的语句不会发出任何javascript,只有Typescript的符号表会更新。
对于一般情况,我希望能够用分号替换任何类声明的主体,从而允许
class Foo<X, Y> extends Bar<X> implements Baz<Y>;
这意味着该库已经保证Foo.prototype是Bar.prototype的实例并实现Baz接口。
@metaweta我认为这可能会带来一些冗余:
interface Foo {
}
class Foo; // Foo is now a class!
interface Bar extends Foo {
}
class Bar extends Foo; // Two `extends Foo`s.
interface X {
}
class X extends Foo; // Hmm?
interface Y extends Foo {
}
class Y; // Hmm?
它仍然具有一定的潜力,因为可子类化的接口可以作为开放式类使用。 #819
@metaweta您的第一种情况应由环境类声明处理。 例如
// myLib.d.ts
declare class Error {
}
// no code emitted here for this.
// myfile.ts
// Error is subclassable,
class MyError extends Error {
}
对于第二种情况,我将为此提出另一个建议问题。
这是ES6规范中“可分类的”对象的完整列表。 目前,这些都定义为接口/变量对。
问题:
可能的解决方案:
@mhegazy谢谢,我没有意识到环境类声明构造。
当我以这种方式(使用环境类定义)扩展Error类时,抛出ExtendedError不会产生堆栈跟踪,也不会正确分配消息。
declare class Error {
constructor(message?: string);
}
class ExtendedError extends Error {
constructor(message?: string) {
super(message + " extended");
}
}
//throw new Error("Test");
throw new ExtendedError("Test");
@unional,这看起来像是引擎问题。 根据ES6规范,它应该可以正常工作。 既然ES6已获得批准,引擎应该修复这些问题。
我设法使它起作用。 在正在运行的js代码中,我有Error.captureStackTrace调用,但是在ts中实现它时将其取出,因为Error声明没有它。
有一个示例代码:
这是一个类似C#的异常,它带有一个innerException。
declare class Error {
public name:string;
public message:string;
public stack:string;
constructor(message?:string);
static captureStackTrace(error: Error, constructorOpt: any);
}
class Exception extends Error {
public innerException: Error;
constructor(message?: string, innerException?: Error|string) {
// Guard against throw Exception(...) usage.
if (!(this instanceof Exception)) return new Exception(message, innerException);
super();
if (typeof Error.captureStackTrace === 'function') {
//noinspection JSUnresolvedFunction
Error.captureStackTrace(this, arguments.callee);
}
this.name = "Exception";
if (innerException) {
if (innerException instanceof Error) {
this.innerException = innerException;
this.message = message + ", innerException: " + this.innerException.message;
}
else if (typeof innerException === "string") {
this.innerException = new Error(innerException);
this.message = message + ", innerException: " + this.innerException.message;
}
else {
this.innerException = innerException;
this.message = message + ", innerException: " + this.innerException;
}
}
else {
this.message = message;
}
}
}
已由#3516修复。 现在,类可以扩展构造函数类型的任意表达式。
该修复程序将发布哪个版本的TypeScript?
我迅速检查了1.5.3和1.5.4的发行标签,似乎它尚未交付,仅暂时存在于母版中。
编辑:
抱歉,现在已经注意到里程碑“ TypeScript 1.6”标记的错误
感谢您的工作!
@kostrse,您可以通过运行npm install -g typescript@next
来试用我们的TypeScript 1.6夜间发行版。
你好
我正在使用打字稿1.6.2和我的lib.es6.d.ts显示错误(和数组
在1.6.2中已经解决了吗?
干杯!
正如@ahejlsberg在https://github.com/Microsoft/TypeScript/issues/1168#issuecomment -112955503中指出的那样, @ jpsfs的修复程序是允许类扩展构造函数类型的任意表达式。
如今,即使有扩展Error
类的能力,Im在节点上仍然不便。 例如,我在“ error.stack”方面遇到麻烦。 当我执行throw new Error(...)
我会得到error.stack
,但是当我执行throw new CustomError()
,我不会。 为了解决这个问题,我不得不使用以下技巧:
export class HttpError extends Error {
httpCode: number;
message: string;
constructor(httpCode: number, message?: string) {
super();
if (httpCode)
this.httpCode = httpCode;
if (message)
this.message = message;
this.stack = new Error().stack;
}
}
最有用的评论
如今,即使有扩展
Error
类的能力,Im在节点上仍然不便。 例如,我在“ error.stack”方面遇到麻烦。 当我执行throw new Error(...)
我会得到error.stack
,但是当我执行throw new CustomError()
,我不会。 为了解决这个问题,我不得不使用以下技巧: