Typescript: クラスで静的な「長さ」関数を定義できません

作成日 2014年08月12日  ·  22コメント  ·  ソース: microsoft/TypeScript

次のtypescriptプログラムが受け入れられます。

class C {
    static length ()  { return "twelve"; }
}

ただし、生成されたコードでは:

var C = (function () {
    function C() {
    }
    C.length = function () {
        return "twelve";
    };
    return C;
})();

ここでは、関数のlengthプロパティに割り当てようとします。 これは(少なくともFirefoxとChromeでは)機能せず、その後のC.length()呼び出しがクラッシュします。 おそらく、静的クラス関数length呼び出しは許可されるべきではありませんか?

codeplex問題#1260から移行されました。

Bug Fixed good first issue help wanted

最も参考になるコメント

一方、ES6 / 2015のネイティブサポートはChromeとFirefoxに導入されました。 これらが問題をネイティブに処理する方法を観察すると、@ nicolo-ribaudoと私が提案したものに近づきます(#9778を参照)。

ネイティブの動作を説明するためのスニペット:

class Foo {
    constructor() {}
}
class Bar {
    static length() {}
    static name() {}
    static caller() {}
}
Foo.name = "FooChanged";
Bar.name = "Baz";

console.log(Foo.name) // Logs "Foo". Foo.name remains unwritable
console.log(Bar.name) // Logs "Baz".  Bar.name became writable

@tinganhonamelength 、およびcallerの読み取り専用性について以前に書いたことに関して、ネイティブ実装では、プロパティがコンストラクター関数で一度書き込み可能であることがわかります。これらのいずれかを静的クラスメンバーとして定義しました(このため、クラス名を取得するためのFunction.nameに関する危険な仮定に関するMDNに関する

したがって、@ nicolo-ribaudoによって提案されているようにObject.definePropertyを使用すると、ネイティブの動作を正確にエミュレートします。 考慮が必要なことは、いくつかの古いがES5互換のブラウザバージョンがプロパティをconfigurable: falseです。 したがって、それらをwritable: trueしようとすると、失敗します(たとえば、 Function.nameの構成可能

要約すると、この問題に関する私の見解は次のとおりです。

  • コンパイルターゲットes3 Object.defineProperty()を使用することはできません。 ただし、 Object.definePropertyないと、ES5環境でES3コードを実行すると、読み取り専用の問題が発生します。 したがって、ターゲットes3コンパイルエラーが必要です。
  • コンパイルターゲットes5に対してObject.defineProperty()writable: trueを使用してコンパイルし、これらのプロパティ名を使用するとブラウザでエラーが発生する可能性があることを示す警告/エラーを発行しますx of version <= yつまり、これらのブラウザをサポートする必要がある場合、最も安全なオプションは別の名前を選択することでした。
  • どうしても他の人にプロパティを使用させたくない場合は、どちらかのターゲットに対してコンパイルエラーを生成します。

コンパイル出力とは関係なく、コンパイラ出力の潜在的な問題についてまったくヒントが得られない今日の状況(TS 1.8.10)よりも、あらゆる種類の追加メッセージの方が良いと思います。

編集:切り取られた追加

全てのコメント22件

私は最近これに遭遇しました。 :(

また、他のいくつかは許可されていません。たとえば、次のコードでエラーが発生するはずです(この機能を実行した場合)。

class C {
    static name = 'something';
    static arguments = 'args';
    static caller = 'caller';
}

console.log(C.name); // 'C'
console.log(C.arguments); // null
console.log(C.caller); // null

ただし、これらのすべてが標準的なわけではありません。

プロパティnamecaller 、およびlengthは実行可能ではないと思います。 これらは読み取り専用のプロパティであり、オーバーライドすることはできません。 それらへのすべての割り当ては無視されます。

@tinganhoは同意しました

わかりましたが、この種のエラーは時々発生するので、TSは何か間違ったことを通知する必要があると思います。 namelengthようなプロパティは覚えておくのがとても自然なので、人々は何度も何度もそれらを再定義しようとします。

レン、名前はすでに定義されているためかもしれません。

私はこれに取り組んでみようと思います。 すでに述べたこととは別に、許可されるべきではないプロパティ名は他にもありますか?

これまでのところ、私は見ています:
長さ、名前、引数、発信者

誰かが禁止された名前の1つで静的プロパティを設定しようとすると、正確に何が起こるはずですか? コンパイラエラー? ユーザーへの目に見える警告?

私はこれに慣れていないので、何かが足りない場合は、いくつかのガイダンスをいただければ幸いです。 :+1:

コンパイルしてみませんか

class C {
    static name = 'something';
    static arguments = 'args';
    static caller = 'caller';
}

console.log(C.name); // 'C'
console.log(C.arguments); // null
console.log(C.caller); // null

のようなものに

var C = (function () {
    function C() {
    }

    C.__statics = {
        name: 'something',
        arguments: 'args',
        caller: 'caller'
    };

    return C;
})();
console.log(C.__statics.name); // 'something'
console.log(C.__statics.arguments); // 'args'
console.log(C.__statics.caller); // 'caller'

stackoverflowにも質問がありました: http

@zerkmsは2か所に同じコメントを投稿しないでください。 ややこしい。

構造型システムでは、名前を勝手に書き換えることができない場合があります。

このようなコードを考えてみましょう

interface HasName {
  name: string;
}
class Foo {
  static name = 'fooClass';
}
let bar: HasName = { name: string };
let q = Math.random() > 0.5 ? Foo : bar;
console.log(q.name);

@RyanCavanaughは確かに公正な例です(私はTSで開発していませんが、

リスクなしにそれらをトランスパイルすることが不可能な場合、おそらくそれらを禁止する必要がありますか?

リスクなしにそれらをトランスパイルすることが不可能な場合、おそらくそれらを禁止する必要がありますか?

間違いなくトランスパイルを変更せず、コンパイルエラーにするだけです:rose:

[...]たぶん私たちはそれらを禁止するべきですか?

一部の進取的な開発者は私たちにPRを送るべきです! :ウィンク:

Object.defineProperty使ってみませんか?

例えば

class C {
    static length() { return "twelve"; }
}

次のようなものに変換されます

var C = (function () {
    function C() {
    }
    Object.defineProperty(C, "length", {
        value: function () { return "twelve"; },
        writable: true
    });
    return C;
}());

@ nicolo-ribaudoそれは確かに機能します。 私の意見:しかし、はそのようなトランスパイルの代わりにエラーを見たいと思います。 TypeScriptは通常、JavaScriptを修正するのではなく、グレースフルエラーの側に傾いています:rose:

TypeScriptは通常、JavaScriptを修正するのではなく、グレースフルエラーの側に傾いています

TSの全体的な考え方は、JSが不可能であり、今後も不可能になるギャップを埋めることによってJSを修正することではありません。

TSの全体的な考え方は、JSが不可能であり、今後も不可能になるギャップを埋めることによってJSを修正することではありません。

はい。 しかし、JavaScriptがどのように機能するかを理解することによって。 nullundefined 。 TypeScriptは両方を理解することを選択しました(Dartがhttps://www.dartlang.org/docs/synonyms/を行うようにそれを単一のものに統合する代わりに)。 間違ったJavaScriptパターンを使用すると、TypeScriptは(トランスパイルで修正する代わりに)エラーを出します:rose:

私の意見は私自身のものであり、私以外の誰にも承認されていません:rose:

一方、ES6 / 2015のネイティブサポートはChromeとFirefoxに導入されました。 これらが問題をネイティブに処理する方法を観察すると、@ nicolo-ribaudoと私が提案したものに近づきます(#9778を参照)。

ネイティブの動作を説明するためのスニペット:

class Foo {
    constructor() {}
}
class Bar {
    static length() {}
    static name() {}
    static caller() {}
}
Foo.name = "FooChanged";
Bar.name = "Baz";

console.log(Foo.name) // Logs "Foo". Foo.name remains unwritable
console.log(Bar.name) // Logs "Baz".  Bar.name became writable

@tinganhonamelength 、およびcallerの読み取り専用性について以前に書いたことに関して、ネイティブ実装では、プロパティがコンストラクター関数で一度書き込み可能であることがわかります。これらのいずれかを静的クラスメンバーとして定義しました(このため、クラス名を取得するためのFunction.nameに関する危険な仮定に関するMDNに関する

したがって、@ nicolo-ribaudoによって提案されているようにObject.definePropertyを使用すると、ネイティブの動作を正確にエミュレートします。 考慮が必要なことは、いくつかの古いがES5互換のブラウザバージョンがプロパティをconfigurable: falseです。 したがって、それらをwritable: trueしようとすると、失敗します(たとえば、 Function.nameの構成可能

要約すると、この問題に関する私の見解は次のとおりです。

  • コンパイルターゲットes3 Object.defineProperty()を使用することはできません。 ただし、 Object.definePropertyないと、ES5環境でES3コードを実行すると、読み取り専用の問題が発生します。 したがって、ターゲットes3コンパイルエラーが必要です。
  • コンパイルターゲットes5に対してObject.defineProperty()writable: trueを使用してコンパイルし、これらのプロパティ名を使用するとブラウザでエラーが発生する可能性があることを示す警告/エラーを発行しますx of version <= yつまり、これらのブラウザをサポートする必要がある場合、最も安全なオプションは別の名前を選択することでした。
  • どうしても他の人にプロパティを使用させたくない場合は、どちらかのターゲットに対してコンパイルエラーを生成します。

コンパイル出力とは関係なく、コンパイラ出力の潜在的な問題についてまったくヒントが得られない今日の状況(TS 1.8.10)よりも、あらゆる種類の追加メッセージの方が良いと思います。

編集:切り取られた追加

@RyanCavanaugh :マイルストーン

PRのタグは、リソースが限られているTypeScriptチームが、これをコミュニティに公開して対処していることを示しています。 この問題に対処したい場合は、TypeScriptコアチームがバックログにリリースに入れるのに十分なスペースがあると感じるまで、より広いコミュニティの誰かがそれに取り組む必要があります(これには長い時間がかかる可能性があります)。

@kitsonkPRレーベルをご説明いただきありがとうございます。 私はそれを理解したと思います。 私が提案したのは、それがまだ問題を処理する正しい方法であるかどうかを再評価することでした。 _name_または_length_と呼ばれる静的クラスプロパティが発生する可能性はそれほど高くなく、TSはそのために誤った出力を生成します。 したがって、私はこの問題を「エッジケース」とは呼びません。

静的プロパティが言語の中核であると考えており、プルリクエストがまだない場合でも、このスレッドで問題の解決策が提示されています。

それでも、私はPRを提供できるかどうかを評価しますが、私はまだTSソースについてそれほど知識がなく、TS2.0が以前にリリースされるのではないかと心配しています。

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

dlaberge picture dlaberge  ·  3コメント

Antony-Jones picture Antony-Jones  ·  3コメント

siddjain picture siddjain  ·  3コメント

manekinekko picture manekinekko  ·  3コメント

wmaurer picture wmaurer  ·  3コメント