2016-08-24 69 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倍,而不是一次。