使用不在参数中的第一个泛型类型重载泛型函数

Posted

技术标签:

【中文标题】使用不在参数中的第一个泛型类型重载泛型函数【英文标题】:Overload generic functions with the first generic type not in parameters 【发布时间】:2020-07-12 22:01:28 【问题描述】:

我在使用如下泛型重载函数时遇到了问题 (playground)。

泛型类型T1 没有在参数中使用(仅用于返回类型),所以当我尝试使用重载#2 时,我必须提供像f<string, string>('123') 这样的所有类型,这有时是不可能的。有没有办法让f<string>('123')匹配overload #2

function f<T1, T2>(t2: T2): T1
function f<T1>(): T1

function f<T1, T2>(t2?: T2): T1 | void 


f<string, string>('123') // ok
f<string>()              // ok
f<string>('123')         // error here, can we fix it by not using f<string, string>('123') ?

function f<T1, T2>(t2: T2): T1
function f<T1>(): T1

function f<T1, T2>(t2?: T2): T1 | void 


f < string, id: number>(id: 123)  // ok
f<string>()                           // ok
f<string>(id:123)                   // typescript complain here can we fix it by not using f<string, string>(id:123) ?

playground

【问题讨论】:

嗯,我曾想过类似function f&lt;T1, T2 = unknown&gt;(t2?: T2): T1f&lt;string&gt;('123')'123' 视为unknown 而不是string... 嗨,我想补充一件事 - 如果这很难理解和执行,也许你不应该让你的代码做到这一点,只需将 f 更改为两种方法以不同的方式处理代码 - 这样可以避免此问题并提高可读性 @MorShemesh,很好的建议。实际上上下文是它是一个可选配置,共享相同的名称是有意义的。但如果我真的不能锻炼,我会选择你的建议。谢谢。 【参考方案1】:

您可以将 T2 的后备添加到 unknownany

function f<T1, T2 = unknown>(t2: T2): T1
function f<T1>(): T1

function f<T1, T2>(t2?: T2): T1 | void 

或者只是对所有情况都有一个声明:

function f<T1, T2 = unknown>(t2?: T2): T1 | void 

// or
function f<T1, T2 = any>(t2?: T2): T1 | void 


【讨论】:

我认为 OP 希望从参数中推断 T2 的类型。 (如果问题在用法示例中使用了不同的类型,而不是string, string,那会更好。) 是的,编辑了回复,不过我不太确定 @T.J.Crowder,是的,我希望从论点中推断出 T@。我刚刚更新了这个问题。谢谢你。 这不起作用,请参阅my comment。 @MorShemesh,它摇滚,谢谢。更新后的playground【参考方案2】:

类型参数可以使用默认值,如果您希望T2T1 相同,可以使用T1 作为默认值:

function f<T1>(): T1
function f<T1, T2 extends T1 = T1>(t2: T2): T1
function f<T1, T2>(t2?: T2): T1 | void 


f<string, string>('123') // ok
f<string>()              // ok
f<string>('123')         // OK

f<number>(123)         // OK

不过,我想提出一个不同的问题。为什么有T2,你不想指定它,只是默认为T1。为什么不直接使用T1。只出现在一个位置(返回类型或参数类型)的类型参数通常是可疑的。类型参数的全部意义在于建立参数之间或参数与返回类型之间的关系。

在不了解您的完整用例的情况下,此功能对我来说更有意义:


function f<T1>(): T1
function f<T1>(t2: T1): T1
function f<T1>(t2?: T1): T1 | void 


f<string>()              // ok
f('123')         // OK

f(123)         // OK

【讨论】:

我原来的例子有点混乱,你能看看这个更新的playground,其中T2是一个对象。希望这是有道理的。

以上是关于使用不在参数中的第一个泛型类型重载泛型函数的主要内容,如果未能解决你的问题,请参考以下文章

Typescript泛型函数重载

Kotlin泛型 ① ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 )

Java泛型方法和构造函数

TypeScript——泛型

Kotlin泛型总结 ★ ( 泛型类 | 泛型参数 | 泛型函数 | 多泛型参数 | 泛型类型约束 | 可变参数结合泛型 | out 协变 | in 逆变 | reified 检查泛型参数类型 )

C++-模板-泛型编程-函数模板-类模板