gpt4 book ai didi

typescript - 使用不同数量的通用参数创建重载时出现问题

转载 作者:搜寻专家 更新时间:2023-10-30 21:12:17 25 4
gpt4 key购买 nike

这个简化代码的最初目的是在 typescript 中创建一个通用方法,它接收一个委托(delegate)和一个对象并返回一个新的委托(delegate),其签名应该与传入的委托(delegate)相同,但是“this”上下文将成为传入对象。

作为伪代码,它应该是这样的:f(del(args: ...parameters), context) => del(this: typeof context, args: ...parameters).

我尝试了几种方法,但都失败了。

下面的代码是最有希望的尝试,但最后也失败了。

在代码中我确实强调了我的问题。基本上,typescript 编译器无法通过 methodWithDelegate 函数的签名自动推断 arg1 和 arg2 的类型。

有解释吗?

有解决办法吗?

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"));

最佳答案

关于为什么会这样,我没有很好的答案。您可能想在 Microsoft/TypeScript 上提出问题要求解释。毫无疑问,泛型类型参数推断、函数参数推断和重载决策之间存在一些相互作用。

显然,一种解决方法是将 val1val2 的类型指定为 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,这就是为什么这是一种变通方法而不是解决方案:

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"));

无论如何,这是我能做的最好的。希望能帮助到你;祝你好运!

关于typescript - 使用不同数量的通用参数创建重载时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46253269/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com