打字稿创建可扩展的嵌套类型

时间:2019-08-22 13:58:06

标签: typescript

我正在尝试创建一个名为Actions的接口,该接口包含一个名为Options的属性,对于不同的操作,该属性会有所不同。

在类型定义中:

export interface Action{
  id?: string;
  type: string;
  options: DrilldownOptions | SidepanelOptions;
}

export interface ActionOptions {
  name: string;
  icon?: any;
  source?: string;
}

export interface DrilldownOptions extends ActionOptions{
  page: string;
}

export interface SidepanelOptions extends ActionOptions{
  widget: any
}

现在,我正尝试在我的执行方法中为每个操作访问这些内容。

因此执行向下钻取动作的执行者将使用

execute(action){
 const page = action.options.page
}

这将导致错误。

  

SidepanelOptions上不存在属性页

是否有更好的方法来实现这种通用类型?

1 个答案:

答案 0 :(得分:0)

如果您有类型为action的变量Action,那么您已经发现,直接访问action.options.page是不安全的:

action.options.page; // error!   Property 'page' does not exist on type 'SidepanelOptions'.

这是因为action.options是联合体类型,并且未知至少在该联合体的一个成员上存在page属性。要安全地访问page,必须使用某种type guardaction.options的类型从DrilldownOptions | SidepanelOptions缩小到DrilldownOptions

例如,从TypeScript 2.7开始,您可以use the in operator as a type guard

if ("page" in action.options) {
  action.options.page.charAt(0); // okay
} else {
  action.options.widget; // okay
}

在“ then”子句中,action.options缩小为DrillDownOptions,在else子句中,action.options缩小为SidepanelOptions

如果要将变量page设置为action.options.page(如果存在),而将变量undefined设置为in,则可以使用const page = "page" in action.options ? action.options.page : undefined; // const page: string | undefined 类型保护符和三元运算符,如下所示:

interface SomeOptions extends ActionOptions {
  page?: string;
  widget?: any;
}

另一种可行的方法是定义一个更广泛的选项类型,如下所示:

DrilldownOptions

SidepanelOptionsSomeOptions都可分配给Action,反之亦然。然后,您可以拥有一个更广阔的interface ActionWider { id?: string; type: string; options: SomeOptions; } 界面:

Action

因此,ActionWider可分配给ActionWider。如果满足您的需求,则可以使用Action代替action。如果没有,您可以像这样安全地加宽const widerAction: ActionWider = action; // okay

const page2 = widerAction.options.page;
// const page2: string | undefined

然后在没有警告的情况下将其编入索引:

page2

请注意,string | undefined的类型为action.options.page,因为undefined可能为page。这与上面的template<enum Foo T = Bar> class Clazz { 分配具有相同的最终结果,而类型保护的争用较少。


好的,希望其中之一能有所帮助。祝你好运!

Link to code