【问题标题】:Union lets me access members that are not common to all typesUnion 让我可以访问并非所有类型都通用的成员
【发布时间】:2017-07-18 13:37:37
【问题描述】:

我要么误解了 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),它是由其他两种类型组成的联合类型,FilterByReportTypeFilterByTag

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(正确地)抱怨 coffeeFlavour 没有t 存在于 FilterByTag 上,这进一步强化了我的工会正在按我希望的方式工作。

为什么在这种情况下我能够访问并非所有联合类型都通用的成员,或者相反,我的用例如何不属于文档中描述的联合范围?

【问题讨论】:

  • 在文档中描述的联合范围内 - 通过 switching 在区分各个类型的内容上,您创建了一个 discriminated union。在每个 case 中,您知道(更重要的是,TypeScript 编译器知道)它是更具体的类型。
  • 我正要回答这个问题,但我不知道 “智能铸造” 的打字稿术语。 +1 @jonrsharpe
  • @jonsharpe 好的,谢谢。但是,除非有扩展的文档,否则您所说的和文档中所说的完全不同。 ` 如果我们有一个联合类型的值,我们只能访问联合中所有类型共有的成员。`
  • @Leahcim 并没有完全不同,上面的链接是 to 相同的文档。您只能访问您不知道自己拥有哪种特定成员类型的普通成员;鉴于您已经明确地分支了代码,每个分支都有更多信息。如果您将页面作为一个整体,它涵盖了许多您可以更具体的情况,例如紧跟在您引用的部分之后的类型保护。它给出了一般规则,然后讨论了各种例外情况。

标签: typescript


【解决方案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 的流分析,它知道actionFilterByTag 类型并且不再FilterAction.

更多

TypeScript 中的可区分联合:https://basarat.gitbooks.io/typescript/content/docs/types/discriminated-unions.html

【讨论】:

  • 我认为它必须具有“种类”属性才能成为可区分的联合
猜你喜欢
  • 1970-01-01
  • 2012-01-14
  • 2022-10-04
  • 2016-02-21
  • 2021-06-21
  • 2013-07-15
  • 1970-01-01
  • 2020-06-07
  • 1970-01-01
相关资源
最近更新 更多