这个简化代码的最初目的是在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"));
答案 0 :(得分:1)
关于为什么会这样,我没有一个很好的答案。您可能希望在Microsoft/TypeScript上提出问题并要求解释。毫无疑问,泛型类型参数推断,函数参数推断和重载决策之间存在一些相互作用。
显然,一种解决方法就是将{
path: 'module2',
loadChildren: './modules/module2/module2.module#Module2Module',
canActivate: [Guard]
}
和val1
的类型指定为val2
...也就是说,放弃复杂的推理游戏,只是明确询问什么你需要:
string
在我看来,无论如何都要做这样的显式注释是好习惯,因为我更愿意陈述我的意图而不是依赖于编译器的(可能是不正确的)推理。但我知道你更喜欢别的东西。
另一种解决方法是没有重载,但允许具有大量可选参数的函数,如下所示:
methodWithDelegate(createDelegate(function(val1: string, val2: string): void {
val1.substring(2);
}, "CONTEXT"));
现在我们正在摆脱处理重载决策的问题,推理会以你想要的方式进行。不幸的是,函数参数是可选的,因此即使它将类型参数推断为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
,这就是为什么这是一个解决方法而不是解决方案:
undefined
无论如何,这是我能做的最好的事情。希望能帮助到你;祝你好运!