2017-09-16 3 views
3

この単純化されたコードの元の目的は、代理人とオブジェクトを受け取るtypescriptでジェネリックメソッドを作成し、渡された委譲しますが、 "this"コンテキストはオブジェクトに渡されます。異なる数のジェネリックパラメータでオーバーロードを作成するときの問題

疑似コードとして、 f(del(args:... parameters)、context)=> del(this:typeof context、args:... parameters)のようになります。

私はいくつかのアプローチを試みましたが、すべて失敗しました。

次のコードは、最も有望だったようですが、最終的には失敗しました。

コードでは私の問題を強調しました。基本的には、typescriptコンパイラは、arg1とarg2の型を自動的にmethodWithDelegate関数のシグネチャを調べることができません。

説明はありますか?

解決策はありますか?

function createDelegate<TContext extends Object, TReturn, A>(fn: (a: A) => TReturn, context: TContext): (this: TContext, a: A) => TReturn 
function createDelegate<TContext extends Object, TReturn, A, B>(fn: (a: A, b: B) => TReturn, context: TContext): (this: TContext, a: A, b: B) => TReturn 
function createDelegate<TContext extends Object, TReturn, A, B, C>(fn: (a: A, b: B, c: C) => TReturn, context: TContext): (this: TContext, a: A, b: B, c: C) => TReturn 
function createDelegate<TContext extends Object, TReturn, A, B, C>(instance: any, funct: Function): any 
{ 
    return <any>funct.bind(instance); 
} 

function methodWithDelegate(delegate: (this: string, val1: string, val2: string) => void) 
{ 
    //delegate invokation 
} 

methodWithDelegate(function (val1, val2) 
{ 
    // OK. val1 and val2 are inferred to be strings. 
    val1.substring(2); 
}); 

methodWithDelegate(createDelegate(function (val1, val2) 
{ 
    // ISSUE: val1 and val2 are not inferred to be strings. they remain of type any 
    val1.substring(2); 
}, "CONTEXT")); 

答えて

1

なぜこのようなことが起こっているのか、大きな回答はありません。説明を求めてMicrosoft/TypeScriptに問題を提出することをお勧めします。間違いなく、ジェネリック型のパラメータ推論、関数パラメータの推論、および過負荷解決の間に相互作用があることは間違いありません。

methodWithDelegate(createDelegate(function(val1: string, val2: string): void { 
    val1.substring(2); 
}, "CONTEXT")); 

で:

は明らかに1つの回避策は...つまり、stringをするval1val2のタイプを指定し、複雑な推論ゲームをあきらめ、ちょうどあなたが必要なものを明確にするために依頼するだけです私の意見では、コンパイラの推論(おそらく誤った推論)に頼るのではなく、私の意図を述べる方が好きなので、このような明示的なアノテーションを行うのがよい方法です。しかし、私はあなたが他の何かを好むことを理解しています。

function createDelegate<Ctx extends Object, R, A=never, B=never, C=never, D=never>(fn: (a?: A, b?: B, c?: C, d?: D) => R, context: Ctx): (this: Ctx, a?: A, b?: B, c?: C, d?: D) => R { 
    return fn.bind(context); 
} 

は、今、私たちはオーバーロードの解決を扱うから自分を解放している

、および:


別の回避策は、このように、過負荷を持っていませんが、オプションのパラメータ数の多い機能を可能にすることです推論はあなたの望むように進む。残念ながら、関数パラメータはオプションであるため、タイプパラメータをstringと推測しても、関数パラメータはstring | undefinedになります。

methodWithDelegate(createDelegate(function(val1, val2) { 
    // handle the possible undefined issue 
    if (typeof val1 === 'undefined') throw new Error("No"); 
    // now the following line works for you 
    val1.substring(2); 
}, "CONTEXT")); 

とにかく私ができる最善だ:だからあなたは、この回避策ではなくソリューションである理由である、機能にundefinedを処理する必要があります。それが役に立てば幸い;がんばろう!

関連する問題