2017-02-10 47 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