基于其他成员类型的条件成员类型

问题描述:

是否可以根据特定条件指定多个可能的成员类型?例如,给予以下类型:基于其他成员类型的条件成员类型

interface DataItem { 
    value: boolean | Date | string | string[]; 
    options: undefined | string[]; 
} 

我想说明,如果:

  • valueboolean类型或Date的那么options必须undefined类型。
  • valuestring型或string[]的然后options必须string[]类型。

有没有办法在当前版本的TypeScript(2.2)中指定上述约束?此外,如果是那么我假设一个部件上添加型后卫应该适用于其他成员,即:

let data: DataItem; 
if (typeof data.value === 'boolean') { 
    data.options = ['a']; // => Error Type 'string[]' is not assignable to type 'undefined'. 
} 

我尝试以下,但没有奏效:

interface BooleanOrDateItem { 
    value: boolean | Date; 
} 

interface StringOrStringArrayDataItem { 
    value: string | string[]; 
    options: string[]; 
} 

type DataItem = BooleanOrDateItem | StringOrStringArrayDataItem; 

let data: DataItem; 

if (typeof data.value === 'string') { 
    // I would expect this to work but the compiler complains 
    // => Property 'options' does not exist on type 'DataItem'. 
    //   Property 'options' does not exist on type 'BooleanOrDateItem'. 
    data.options = ['a']; 
} 

明确铸造StringOrStringArray明显作品

if (typeof data.value === 'string') { 
    (<StringOrStringArrayDataItem>data).options = ['a']; 
} 

但不应编译器做的我的代表,因为它有足够的信息来推断dataStringOrStringArrayDataItem

+0

我觉得这种方法是行不通的,我会使用'任何'数据类型或创建多个接口,并找出你需要使用工厂。 –

我相信你正在寻找User-defined Type Guards。在每个if语句之后,如果返回值为true,TypeScript会将dataItem的类型缩小为正确的类型。

interface DataItem { 
    value: boolean | Date | string | string[]; 
    options: undefined | string[]; 
} 

interface BoolOrDateDataItem extends DataItem { 
    value: boolean | Date; 
    options: undefined; 
} 
interface StringDataItem extends DataItem { 
    value: string | string[]; 
    options: string[]; 
} 

function isBoolOrDateDataItem(dataItem: DataItem): dataItem is BoolOrDateDataItem { 
    return typeof dataItem.value === 'boolean' || dataItem.value instanceof Date; 
} 

function isStringDataItem(dataItem: DataItem): dataItem is StringDataItem { 
    return typeof dataItem.value === 'string' || dataItem.value instanceof Array; 
} 

let dataItem: DataItem = { 
    value: true, 
    options: undefined 
} // Or whatever it may be 

if (isStringDataItem(dataItem)) { 
    dataItem.value = new Date(); // TypeScript warns value must be string | string[] - knows it is a StringDataItem here 
} else if (isBoolOrDateDataItem(dataItem)) { 
    dataItem.value = true; // No error 
} 

这绝对有点冗长,但似乎是推荐的做事方式。