2017-03-22 13 views
4

EDIT:これはTypescriptの既知の問題です。 A solution was once implementedですが、最終的に解決できないパフォーマンスの問題が原因で取り除かれます。Typescript:クラスメソッドの暗黙の `this`タイプ

このような状況は、私たちのコードベースに頻繁に来る:

function consumer<T>(valueProducer:() => T) { 
    let value = valueProducer(); 
    console.log(value); 
} 

class Foo { 
    private _value: number = 100; 

    getValue(): number { 
     return this._value; 
    } 

    constructor() { 
     // Oops! Inside consumer(), getValue will be called with wrong this 
     consumer(this.getValue); 
    } 
} 

活字体でのソリューションはこのいずれかである:この問題は明白であるかもしれない

consumer(this.getValue.bind(this)); // bind to correct this 

consumer(() => this.getValue()); // capture correct this 

またはこのTypescript/Javascriptのプログラマに、私たちのチームはC#の大部分をTypescriptに移植しています。そしてC#では、これはではありません。 C#で渡されたメソッドは自動的にパッセンジャーにバインドされます)。可能であれば、タイプシステムにこのエラーをキャッチしたいと思います。

明示的にコールバックに使用this入力する最初の、明確なステップ:

function consumer<T>(valueProducer: (this: void) => T) { 
    let value = valueProducer(); 
    console.log(value); 
} 

が、私はそれが十分であることを期待し、それは私が明示的Fooの上thisパラメータを入力する必要が判明方法:

error TS2345: Argument of type '(this: Foo) => number' is not assignable to parameter of type '(this: void) => number'. 
    The 'this' types of each signature are incompatible. 
    Type 'void' is not assignable to type 'Foo'. 
:代わりにこれら二つのもので

class Foo { 
    getValue(this: Foo): number { // I could also have written getValue(this: this) 
     return this._value; 
    } 

、私は今、私が望む正確にエラーが発生します

私のアプリのすべてのメソッドにthis: thisを追加する必要はありません。メソッド内のthisの値は、暗黙的に囲み型の値でなければなりませんか?その定型的なノイズをすべてクラスに追加しなければ、同じ結果を達成する別の方法はありますか?私の視点から

function consumer<T>(valueProducer:() => T, thisArg: any) { 
    let value = valueProducer.apply(thisArg); 
    console.log(value); 
} 

class Foo { 
    private _value: number = 100; 

    getValue(): number { 
     return this._value; 
    } 

    constructor() { 
     consumer(this.getValue, this); 
    } 
} 

:あなたはmapのような作り付けのjavascript機能もthis明示的にサポートするのと同じように、コールバックに明示的this引数を渡すことができ

+0

JS/TSの慣用方法は、あなたが言及したとおりです:コールバックに既にバインドされた関数を提供します。これはJSの文脈では難しいビジネスですが、できるだけ避けるのが最善です。 –

+1

ええ、私は正しくコールバックを渡す方法を知っています。私は型システムが私にそれを渡すかどうかを知らせたいと思っています*正しくタイプされていますか?コンパイラに、 'Foo'メソッドの中の' this'が 'Foo'型であることを明示的に伝えるだけで、私にはすでに分かっているはずのものがわかります。だから私は何かが欠けていることを望んでいる(コンパイラフラグ、たぶん?)可能性が高いのは、Typescriptがうまくいっている理由だ。 :) – Mud

答えて

0

plunker for discussed code)矢印関数アプローチより醜いですが、少なくともあなたはそれを渡すことを忘れることはできません。

+0

私はそれが答えではないと思います。なぜなら、「消費者(...)」関数に「this」を呼び出す関数を渡したくないからです。私が正しいことを理解すれば、彼は拘束エラーをしたい。 – Diullei

+0

私はそれを知っています。残念ながら、私はより良いものを与えることはできません:(私は、これを正しくバインドしたメソッドまたはこれを必要としない自立機能は、現在typescriptで表現できるとは思わない。しかし、より良い答えを知っていれば、私も興味があります。 – Matthias247

+0

はい、確かです。私はそれをする方法もないと思う。 – Diullei

関連する問題