2017-04-04 44 views
1

比方說,我有以下類型的地圖:索引類型映射可以擴展爲區分的工會嗎?

type MyTypes = { 
    'float': number; 
    'text': string; 
    'bool': boolean; 
    'price': number; 
    'date': Date; 
}; 

我想自動生成一個區分聯合類型。這樣做的相當於:

type Datum<K, V> = { type: K, value: V }; 

type MagicUnionMaker<TypeMap> = (
    // pretend the below is auto-generated from TypeMap 
    Datum<'float', number> | 
    Datum<'text', string> | 
    Datum<'bool', boolean> | 
    Datum<'price', number> | 
    Datum<'date', Date> 
); 

哪位能像這樣被使用:

interface DataModel<TypeMap> { 
    data(row: number, col: number): MagicUnionMaker<TypeMap>; 
} 

let model: DataModel<MyTypes>; 
let datum = model.data(0, 0); 
switch (datum.type) { 
    case 'float': 
    // datum.value is `number` 
    break; 
    case 'text': 
    // datum.value is `string` 
    break; 
    case 'bool': 
    // datum.value is `boolean` 
    break; 
    case 'price': 
    // datum.value is `price` 
    break; 
    case 'date': 
    // datum.value is `Date` 
    break; 
    case 'thing': // error 
    break; 
} 

是這樣目前可能嗎?

+0

AFAIK映射到聯合不可用(還)。我想工會的一部分必須由人寫。 – Jokester

回答

3

不完全是,它似乎你不能有通用UnionMaker,並且需要每次你需要它的時候,構建就地聯盟類型:

type MyTypes = { 
    'float': number; 
    'text': string; 
    'bool': boolean; 
    'price': number; 
    'date': Date; 
}; 

type TypeDataMap<T> = {[K in keyof T]: {type: K, value: T[K]}}; 

interface MyDataModel { 
    data(row: number, col: number): TypeDataMap<MyTypes>[keyof MyTypes]; 
} 

let model: MyDataModel; 
let datum = model.data(0, 0); 
// type inference works as expected 
switch (datum.type) { 
    case 'float': 
    let n: number = datum.value; 
    break; 
    case 'text': 
    let s: string = datum.value; 
    break; 
    case 'bool': 
    let b: boolean = datum.value; 
    break; 
    case 'price': 
    let p: number = datum.value; 
    break; 
    case 'date': 
    let d: Date = datum.value; 
    break; 
    case 'thing': // error: Type '"thing"' is not comparable to type 
       // '"float" | "text" | "bool" | "price" | "date"'. 
    break; 
} 

試圖構建相當於泛型類型失敗:

// does not work 
type UnionMaker<T> = TypeDataMap<T>[keyof T]; 

type MyTypeMap = UnionMaker<MyTypes>; 
// because MyTypeMap gets inferred for some reason as 
// type MyTypeMap = { 
//  type: "float" | "text" | "bool" | "price" | "date"; 
//  value: string | number | boolean | Date; 
// } 
// which is NOT what you want 
相關問題