TypeScript - 如何将索引签名表示为泛型类型

Posted

技术标签:

【中文标题】TypeScript - 如何将索引签名表示为泛型类型【英文标题】:TypeScript - How to represent an index signature as a generic type 【发布时间】:2017-02-10 09:25:32 【问题描述】:

TypeScript 中的索引签名是这样定义的:

字典

[key: string]: T

数组

[index: number]: T

这些可以包装成一些简单的、可重用的类型:

type DictionaryIndex<T> = 
    [key: string]: T


type ArrayIndex<T> = 
    [index: number]: T

现在我想将它们包装成一个类型。我试过这个:

type Index<TKey extends string|number, TValue> = 
    [key: TKey]: TValue

由于以下错误,无法编译:

索引签名参数必须是“字符串”或“数字”类型。

这不可能吗?

到底是为了什么?

因为

foo(obj: Index<string, Bar>)
foo(obj: Index<string, Bar> & Fooable<string>)

看起来比

更整洁
foo(obj:  [key: string]: Bar )
foo(obj:  [key: string]: Bar, canFoo: (foo: string) => Bar )

【问题讨论】:

TypeScript repo 上有一个关于此的问题:github.com/Microsoft/TypeScript/issues/13398 Guess it is not possible. 【参考方案1】:

很酷的问题! 我认为原因是这对于尚未实现的编译器来说确实是一个边缘案例,可能是因为它不值得付出努力。

索引属性键只能是明显的数字,对象属性键只能是字符串或数字。所以最后你的约束只说明什么是事实,以及编译器需要通过特殊情况处理什么。 所以我再次假设圣安德斯放弃了这一努力;-)

但为什么不这样做

type StrIndex<TValue> = 
    [key: string]: TValue


type NumIndex<TValue> = 
    [key: number]: TValue


foo(obj: StrIndex<Bar>)
foo(obj: StrIndex<Bar> & Fooable<string>)

它不像您的解决方案那样简洁,但作为一种折衷方案,它似乎还可以,因为 XXXIndex 类型的集合限制为 2 个

【讨论】:

【参考方案2】:

另一种解决方案是使用Record 实用程序。

foo(obj: Record<string, Bar>)

https://www.typescriptlang.org/docs/handbook/utility-types.html#recordkeys-type

【讨论】:

以上是关于TypeScript - 如何将索引签名表示为泛型类型的主要内容,如果未能解决你的问题,请参考以下文章

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

Typescript 从具有泛型类型的对象索引调用函数

如何将d:DesignInstance设置为泛型类型?

TypeScript,啥是对象文字的调用签名以及它们如何与泛型类型一起使用?

如何将“任何不可为空的类型”指定为泛型类型参数约束?

如何将字符串反序列化为对象,然后在颤振中设置为泛型