2017-08-25 70 views
1

因此,我發現在打字稿中有一個技巧,通過將類型映射到鍵值對,然後使用keyof類型創建可以是地圖中的任何值的類型,將對象類型轉換爲區分的聯合。下面是一個簡單的例子:泛型中[typof T]的原因與硬編碼類型有不同的語義?

type SourceType = 
{ 
    foo: number, 
    bar: string 
}; 
type MapWithKey<T> = {[P in keyof T]: { key: P, value: T[P] }} 
type DescriminatedUnion = MapWithKey<SourceType>[keyof SourceType]; 
//The DescriminatedUnion now has the following type 
DescriminatedUnion ≡ {key:"foo",value:string} | {key:"bar",value:number} 

,如果你想,當你試圖使這個結構完全通用的,你最終有一個不同類型但指定一個非常大的可識別聯合,這是非常有用的。

type MakeDescriminatedUnion<T> = MapWithKey<T>[keyof T]; 
type DescriminatedUnion = MakeDescriminatedUnion<SourceType> 
//The DescriminatedUnion now has the followin type 
DescriminatedUnion ≡ {key:"foo"|"bar",value:number|string} 

這應該是相同的類型,但由於某種原因它不是。我試圖通過打字稿找到一些推理,但我不能。有誰知道這種差異的原因嗎?或者甚至更好,有人知道一種方法來解決這種行爲,並使其完全通用?

+3

[此問題](https://stackoverflow.com/questions/43898999/creating-a-discriminated-union-using-the-property-names-of-another-type)看起來非常相似,這裏是[github問題](https://github.com/Microsoft/TypeScript/issues/15756)和[這裏是修復](https://github.com/Microsoft/TypeScript/pull/18042) – artem

+0

謝謝!這比我預想的要多得多。 @artem –

回答

1

是的,this issue已經咬了mequite幾個others。令人驚訝的是,正如@artem提到的那樣,a fix將在今天推出!

同時,對於我們這些被困在打字稿2.4的土地,有使用default generic type parameters解決方法:

type MakeDiscriminatedUnion<T, M extends MapWithKey<T> = MapWithKey<T>> = M[keyof T]; 
type DiscriminatedUnion = MakeDiscriminatedUnion<SourceType> // okay now 

M的實際價值沒有得到評估,直到您使用MakeDiscriminatedUnion<SourceType>,所以編譯器沒有機會像上面那樣「簡化」M[keyof T]

無論如何,無論是使用解決方法還是等待TypeScript 2.6,都是您的選擇。希望有所幫助。祝你好運!

+0

感謝您的解決!無法在其他地方找到它完美無缺的工作! –