如何编写使用两个接口之一的类型?

时间:2019-09-08 10:09:30

标签: typescript

函数<div data-v-28f44f54 class="data-set"> <div data-v-28f44f54 class="type"> 必须接受签名为
的对象 pharma['Date_diff_cumsum'] = pharma.groupby('ID').Date.diff().dt.total_seconds() // 60.0 pharma['Value'] = pharma['Value'].apply(lambda x: xOperations) pharma['Date_diff_cumsum'] = pharma['Date_diff_cumsum'].fillna(0) pharma['weigth'] = pharma['ID'].map(weigth.set_index('ID') ['Value']).fillna(0) pharma['TempVal'] = (pharma['Value']/(pharma['Weigth'] * pharma['Date_diff_cumsum'])).fillna(0)

foo

parentId: string; id: string; text: string;

TS说parentId: string; id: string; type: "separator";。 那么如何在没有代码重复的情况下实现这种键入呢?

1 个答案:

答案 0 :(得分:0)

问题在于并集类型确实意味着它是一个或另一个。因此,TypeScript不允许您访问text属性,因为它在两个接口上都不存在。

铸造

在不更改类型的任何内容的情况下,您将不得不强制转换以使其编译:

function foo(item: IMenuItem): void {
  console.log((item as ITextItem).text);
}

歧视联盟

或者,您可以使用discriminated unions。为此,您需要在type: "text"界面中添加一个ITextItem属性。

interface ITextItem extends IMenuItemGeneric {
  type: "text";
  text: string;
}

由于两个接口现在都具有type属性,因此您无需进行铸造就可以访问它。更重要的是,编译器将使用它来缩小传递项目的实际类型:

function foo(item: IMenuItem): void {
  if (item.type === 'text') {
    // type inside here is ITextItem
    console.log(item.text);
  } else {
    // type inside here is ISeparatorItem
  }
}

Playground

合并类型

最后,如果您希望item的类型中所有非常见属性都可能未定义,如下所示:

{
    parentId: string;
    id: string;
    type?: "separator";
    text?: string;
}

您可以改为:

export type IMenuItem = Partial<ITextItem> & Partial<ISeparatorItem> & IMenuItemGeneric;

在这种情况下,甚至可以使用解构参数:

function foo({
  parentId,
  id,
  text,
  type
}: IMenuItem): void {
  console.log(text); // text has type: string | undefined
}

Playground


哪种方法最适合您是很难说的。这很大程度上取决于您在foo内部的工作。