我有一个对象数组,每个对象都有不同的类型。
我正在使用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 :\
答案 0 :(得分:0)
您的结构将reportData
强制为IReportItem
类型,即IReportItemRegions
或IReportItemFactionStatus
,因为它是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