2017-02-10 61 views
2

索引签名被如此定义:打字稿 - 如何打字原稿代表索引签名作为一个通用型

字典

[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 
} 

这并不编译由于以下错误:

An index signature parameter must be of type 'string' or 'number'.

这是不可能的?

这到底是为了什么?

因为

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 }) 
+0

在TypeScript repo上存在一个问题:https://github.com/Microsoft/TypeScript/issues/13398 猜猜这是不可能的。 –

回答

2

凉爽的问题!
我认为原因在于这对编译器来说确实是一个边缘情况,因为它不值得付出努力。

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

但为什么不能做到这一点

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

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

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

它不是像您的解决方案的整洁,但作为一种妥协它专门似乎确定为集合的XXXIndex类型被限制为2