2016-08-24 2 views
1

Почему я не в состоянии получить доступ атрибутов в типах союза, как это:Невозможно доступа к параметрам из типов союза (машинопись)

export interface ICondition { 
    field: string 
    operator: string 
    value: string 
} 

export interface IConditionGroup { 
    conditions: ICondition[] 
    group_operator: string 
} 

function foo(item: ICondition | IConditionGroup) { 
    if(typeof item.conditions === "undefined") { // does not work 
    let field = item.field; // does not work 
    ///.. do something 
    } else { 
    let conditions = item.conditions; // does not work 
    /// .. do something else 
    } 
} 

я получаю эти ошибки:

error TS2339: Property 'conditions' does not exist on type 'ICondition | IConditionGroup'. 
error TS2339: Property 'conditions' does not exist on type 'ICondition | IConditionGroup'. 
error TS2339: Property 'field' does not exist on type 'ICondition | IConditionGroup'. 

Но я должен бросить типы, чтобы заставить его работать - вот так:

function foo2(inputItem: ICondition | IConditionGroup) { 
    if(typeof (<IConditionGroup>inputItem).conditions === "undefined") { 
    let item= (<ICondition>inputItem); 
    let field = item.field; 
    ///.. do something 
    } else { 
    let item= (<IConditionGroup>inputItem); 
    let conditions = item.conditions; 
    /// .. do something else 
    } 
} 

Я понимаю, что информация о типе теряется в JS, так почему я должен явным образом бросил его в TS?

ответ

4

Машинопись обрабатывает это с Type Guards, как правило, это так просто, как:

if (typeof item === "string") { ... } else { ... } 

Или

if (item instanceof MyClass) { ... } else { ... } 

Но в вашем случае, как вы используете интерфейсы, которые не представляется возможным, так что вам нужно чтобы создать свой собственный User-Defined Type Guards:

function isConditionGroup(item: ICondition | IConditionGroup): item is IConditionGroup { 
    return (item as IConditionGroup).conditions !== undefined; 
} 

function foo(item: ICondition | IConditionGroup) { 
    if (isConditionGroup(item)) { 
     let conditions = item.conditions; 
     // do something 
    } else { 
     let field = item.field; 
     // do something else 
    } 
} 

(code in playground)

Вы также можете сделать это без охраны типа:

function foo(item: ICondition | IConditionGroup) { 
    if ((item as IConditionGroup).conditions !== undefined) { 
     let conditions = (item as IConditionGroup).conditions; 
     // do something 
    } else { 
     let field = (item as ICondition).field; 
     // do something else 
    } 
} 

Но это способ говорящими, насколько вам нужно набрать утверждать item 3 раза вместо одного.

Смежные вопросы