我要么误解TypeScript中的联合类型,要么文档不正确。在advanced types部分中,它使用以下示例说明:
如果我们有一个具有联合类型的值,我们只能访问成员 这对于工会中的所有类型都是通用的。
interface Bird { fly(); layEggs(); } interface Fish { swim(); layEggs(); } function getSmallPet(): Fish | Bird { // ... } let pet = getSmallPet(); pet.layEggs(); // okay pet.swim(); // errors
然而,在我目前的TypeScript项目中,我似乎完全按照我所说的那样做。我创建了一个类型(FilterAction
),它是由另外两种类型FilterByReportType
和FilterByTag
组成的联合类型:
export type FilterAction = FilterByReportType | FilterByTag | FilterByCoffeeFlavour
export interface FilterByType {
type: constants.FILTER_BY_TYPE;
report_type: string;
}
export interface FilterByTag {
type: constants.FILTER_BY_TAG;
tag: string;
}
export interface FilterByCoffeeFlavour {
type: constants.FILTER_BY_COFFEE_FLAVOUR;
coffeeFlavour: string;
}
action
(因为它被调用)被传递给一个打开该类型的函数,然后(这是令人惊讶的部分)它能够访问该成员并不是联盟中所有类型的共同点。
function filters(state: Filter = initialState, action: FilterAction) : Filter {
switch (action.type) {
case c.FILTER_BY_TAG:
return Object.assign({}, state, { filterType: "tag", secondaryFilter: action.tag}) //accessing the uncommon member here w/o problem
case c.FILTER_BY_REPORT_TYPE:
return Object.assign({}, state, { filterType: action.report_type, secondaryFilter: ""})
case c.FILTER_BY_COFFEE_FLAVOUR:
return Object.assign({}, state, { filterType: action.coffeeFlavour, secondaryFilter: ""})
default:
return state;
}
}
此外,例如,当我打开FILTER_BY_TAG
并尝试从其他类型之一(例如coffeeFlavour
)访问成员时,那么TypeScript(正确地)会抱怨{ FilterByTag上不存在{1}},这进一步强化了我的工会正如我所希望的那样工作。
为什么在这种情况下我能够访问所有类型的联合并不常见的成员,或者相反,我的用例如何不进入文档中描述的联合范围?
答案 0 :(得分:1)
这是您希望发生错误但未发生错误的行:
return Object.assign({}, state, { filterType: "tag", secondaryFilter: action.tag}) //accessing the uncommon member here w/o problem
它没有发生的原因:因为它在case c.FILTER_BY_TAG:
下面这告诉TypeScript 类型并且由于TypeScript的流分析,它知道action
的类型为{{ 1}}而不再是FilterByTag
。
TypeScript中的歧视联盟:https://basarat.gitbooks.io/typescript/content/docs/types/discriminated-unions.html