次の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から移行されました。
私は最近これに遭遇しました。 :(
また、他のいくつかは許可されていません。たとえば、次のコードでエラーが発生するはずです(この機能を実行した場合)。
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
ただし、これらのすべてが標準的なわけではありません。
プロパティname
、 caller
、およびlength
は実行可能ではないと思います。 これらは読み取り専用のプロパティであり、オーバーライドすることはできません。 それらへのすべての割り当ては無視されます。
@tinganhoは同意しました
わかりましたが、この種のエラーは時々発生するので、TSは何か間違ったことを通知する必要があると思います。 name
やlength
ようなプロパティは覚えておくのがとても自然なので、人々は何度も何度もそれらを再定義しようとします。
レン、名前はすでに定義されているためかもしれません。
私はこれに取り組んでみようと思います。 すでに述べたこととは別に、許可されるべきではないプロパティ名は他にもありますか?
これまでのところ、私は見ています:
長さ、名前、引数、発信者
誰かが禁止された名前の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がどのように機能するかを理解することによって。 null
とundefined
。 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
@tinganhoがname
、 length
、および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が以前にリリースされるのではないかと心配しています。
最も参考になるコメント
一方、ES6 / 2015のネイティブサポートはChromeとFirefoxに導入されました。 これらが問題をネイティブに処理する方法を観察すると、@ nicolo-ribaudoと私が提案したものに近づきます(#9778を参照)。
ネイティブの動作を説明するためのスニペット:
@tinganhoが
name
、length
、および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)よりも、あらゆる種類の追加メッセージの方が良いと思います。
編集:切り取られた追加