在不同类型的数组中查找打字稿

时间:2019-01-18 06:50:23

标签: javascript typescript

我有一个对象数组,每个对象都有不同的类型。 我正在使用Array.find(或循环,没有区别)从数组中获取对象之一。现在,除非我添加其他|| reportData.type !== "REGIONS"检查,否则Typescript无法理解我从数组中获取的类型。还有其他解决方法吗?

 export interface IReportItemFactionStatus {
    type: "FACTION_STATUS";
  }

  export interface IReportItemRegions {
    type: "REGIONS";
    regions: [];
  }

  export type IReportItem = IReportItemRegions | IReportItemFactionStatus;

  export type IReport = Array<IReportItem>;

  // ... code ...
  // report has type IReport

  const reportData = report.find((d) => {
      return d.type === "REGIONS";
  });

  if (!reportData) {
    return [];
  }
  console.log(reportData.regions); // Typescript error here

但是,如果我为reportData.type添加其他检查,它将开始正常工作

  if (!reportData || reportData.type !== "REGIONS") {
    return [];
  }
  console.log(reportData.regions); // No Typescript error here :\

2 个答案:

答案 0 :(得分:0)

您的结构将reportData强制为IReportItem类型,即IReportItemRegionsIReportItemFactionStatus,因为它是report数组的元素。

您要显示属性regions,该属性仅在接口IReportItemRegions中实现。我们不知道reportData是否为IReportItemRegions类型。在尝试访问该属性之前,必须确保您的对象实现了该属性:

if ('regions' in reportData) {
  console.log(reportData.regions)
}

如果要TypeScript推断类型,则必须摆脱find并重写代码。我提供了一个简单的实现:

let reportData: IReportItemRegions;
let i = 0;
while (!reportData && report.length < i) {
  const currentReportData = report[i];
  if (currentReportData.type === 'REGIONS') {
    // Typescrit knows currentReportData is of type IReportItemRegions
    reportData = currentReportData;
  }
  i++;
}

if (!reportData) {
  return [];
}
console.log(reportData.regions);

答案 1 :(得分:-1)

TS抛出错误,因为返回值将为IReportItemRegions | IReportItemFactionStatus类型。

如果其类型为IReportItemFactionStatus,因为其中没有regions。因此它应该引发错误。

添加此检查:reportData.type !== "REGIONS"时,您是在告诉打字稿,对于遇到IReportItemFactionStatus的情况,您是在返回之前,并且console.log(reportData.regions);变为无法访问的代码。因此没有错误。


替代方式:

enum ReportType {
  REGIONS = "REGIONS",
  FACTION_STATUS = "FACTION_STATUS"
}

export interface IReportItem {
  type: ReportType;
  regions?: [];
}

// No need for this now
//export type IReportItem = IReportItemRegions | IReportItemFactionStatus;

export type IReport = Array < IReportItem > ;

// ... code ...
// report has type IReport

const reportData: IReportItem | null = report.find((d) => {
  return d.type === ReportType.REGION;
});

if (!reportData) {
  return [];
}
console.log(reportData.regions); // Typescript error here