Typescript - 具有通用类型函数的索引签名

Posted

技术标签:

【中文标题】Typescript - 具有通用类型函数的索引签名【英文标题】:Typescript - index signatures with generically typed functions 【发布时间】:2020-12-24 12:43:52 【问题描述】:

是否可以在 Typescript 中定义具有索引签名的接口,其中索引引用的属性值是同一泛型类型的不同类型?

让我试着解释一下:

我有一个具有以下通用签名的函数 Foo:

interface Foo<T> (arg1: Moo<T>): T
interface Moo<N> nest: N

然后是一个对象,它将由一堆 Foo 类型的函数组成,但每个函数都有不同的泛型参数。所以:

interface Foos 
    bar: Foo<number>,
    baz: Foo<string>


const foos:Foos = 
    bar: x => x.nest,
    baz: y => y.nest

但我不想在界面中明确定义每个函数。我想要类似的东西:

interface FoosTwo [K:string]: Foo<any>

const foosTwo:FoosTwo = 
    bar: x => x.nest,
    baz: y => y.nest

但是,当然,如果我这样做,我在 foosTwo.bar 和 foosTwo.baz 上失去了任何类型的真正打字——它们都只是Foo&lt;any&gt;。这是有道理的——编译器怎么知道我想要什么?

但是有没有办法告诉编译器 Foo 的泛型类型是什么,内联,即类似这样的东西(我意识到这不起作用)?

interface FoosTwo [K:string]: Foo<any>

const foosTwo:FoosTwo = 
    bar<number>: x => x.nest,
    baz<string>: y => y.nest

换句话说,有没有办法给编译器提供足够的信息来确定 bar 是 Foo&lt;number&gt; 和 baz 是 Foo&lt;string&gt; 而无需为每个函数显式定义完整类型?

非常感谢

【问题讨论】:

不确定是否有帮助,但方法与***.com/a/63777650/1113002 中的方法相同。试试playground 是的,您和@jonrsharpe 在那篇文章中的 cmets 让我对索引字符串有了一点了解。我会玩一点,看看这是否能给我我需要的解决方案。谢谢! 【参考方案1】:

根据上面@aleksey-l 的建议,我现在看到解决方案很简单。

将其视为索引签名的问题(这是我正在做的)是错误的。像 [K:string] 或 Record(string, any) 这样的索引签名必然是松散的,因为它们对于满足签名的任何内容都必须相同。这就是为什么我能做的最好的事情是interface FoosTwo [K:string]: Foo&lt;any&gt;

事实证明,我真正希望 TS 做的是推断一个强类型接口,就像我上面列出的手动接口:

interface Foos 
    bar: Foo<number>,
    baz: Foo<string>

做到这一点的方法是使用标识函数和泛型让 TS 基本上吸收一些输入信息,然后使用它来输入最终函数。所以这个:

function createFoo<T>(func: Foo<T>):Foo<T> 
    return func


const foosTwo = 
    bar: createFoo<number>(x => x.nest),
    baz: createFoo<string>( y => y.nest)

一个简单的标识函数,它使用泛型提供的“提示”以我想要的方式键入返回的(相同的)函数。 @alexksey-l 的解决方案同样有效,尽管它的表述与我提出的问题略有不同。他得到了答案(并且让我看到了使用泛型的一些力量)。

这里是 a playground 的完整解决方案。

【讨论】:

【参考方案2】:

一个选项:

const foosTwo = 
    bar: (x => x.nest) as Foo<number>,
    baz: (y => y.nest) as Foo<string>

【讨论】:

谢谢。我想我希望尽可能避免铸造。该对象将具有由不同开发人员添加的功能,我宁愿推断功能接口而不是依靠人们提供正确的演员表。也就是说,我确实认为这是一种改进。

以上是关于Typescript - 具有通用类型函数的索引签名的主要内容,如果未能解决你的问题,请参考以下文章

具有通用联合约束的 TypeScript 函数返回值

映射具有未知深度的通用 TypeScript 接口

具有通用方法的Typescript接口

您如何定义具有键字符串索引但具有特定类型的已知键的 TypeScript 接口?

TypeScript:元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型

TypeScript - 元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型