ES6は、いくつかのネイティブオブジェクトをサブクラス化可能として指定します。たとえば、Object、Boolean、Error、Map、Promiseなどです。 これらの構造がlib.d.tsでモデル化される方法は、変数とインターフェースのペアとして定義されているため、サブクラス化することは不可能です。
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 {
}
2番目のケースでは、別の提案の問題を提出します。
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呼び出しがありますが、Error宣言にないため、tsに実装すると削除されます。
サンプルコードがあります:
これは、innerExceptionを受け取るC#のような例外です。
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のリリースラベルをすばやく確認しましたが、まだ出荷されていないようで、現時点ではマスターのみです。
編集:
申し訳ありませんが、マイルストーン「TypeScript1.6」でマークされたバグに気づきました
お疲れ様でした!
@kostrse npm install -g typescript@next
実行すると、TypeScript1.6の夜間リリースを試すことができます。
こんにちは、
Typescript 1.6.2を使用していますが、lib.es6.d.tsにエラー(および配列)が表示されます
これは1.6.2ですでに修正されていますか?
乾杯!
@jpsfsの修正は、 https: //github.com/Microsoft/TypeScript/issues/1168#issuecomment -112955503の@ahejlsbergで指摘されているように、クラスがコンストラクター関数型の任意の式を拡張できるようにすることです。
今日ではError
クラスを拡張する機能がありますが、Imはまだノードでそれを使用することに不便を感じています。 たとえば、「error.stack」で問題が発生しています。 throw new Error(...)
を実行すると、 error.stack
throw new Error(...)
を取得しますが、 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 Error(...)
を取得しますが、throw new CustomError()
を実行すると、取得しません。 それを解決するために、私はこのトリックを使用することを余儀なくされました: