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

ser*_*0ne 9 generics generic-constraints typescript

因此,定义了TypeScript中的索引签名:

字典

[key: string]: T
Run Code Online (Sandbox Code Playgroud)

排列

[index: number]: T
Run Code Online (Sandbox Code Playgroud)

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

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

type ArrayIndex<T> = {
    [index: number]: T
}
Run Code Online (Sandbox Code Playgroud)

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

type Index<TKey extends string|number, TValue> = {
    [key: TKey]: TValue
}
Run Code Online (Sandbox Code Playgroud)

由于以下错误,这不会编译:

索引签名参数必须是"string"或"number"类型.

这不可能吗?

到底是为了什么?

因为

foo(obj: Index<string, Bar>)
foo(obj: Index<string, Bar> & Fooable<string>)
Run Code Online (Sandbox Code Playgroud)

看起来比

foo(obj: { [key: string]: Bar })
foo(obj: { [key: string]: Bar, canFoo: (foo: string) => Bar })
Run Code Online (Sandbox Code Playgroud)

rob*_*kuz 5

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

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

但为什么不这样做

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

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

foo(obj: StrIndex<Bar>)
foo(obj: StrIndex<Bar> & Fooable<string>)
Run Code Online (Sandbox Code Playgroud)

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