升级Angular17遇TypeScript错误:'resRemarks'属性不存在于string类型
问题描述
将Angular 12项目升级到Angular 17后,原代码出现TypeScript类型错误:代码通过this.pmlaCheck[d.results](d是this.pmlaDbData数组元素,results存储PmlaCheck接口的属性名,如"cibilSfcResults")访问对应子对象并读取resRemarks属性时,TypeScript提示该属性不存在于string类型。已通过d.results as keyof PmlaCheck解决索引类型错误,现需解决属性访问的类型报错。
相关接口定义:
export interface PmlaCheck { _id?: string; cibilSfcResults: CibilSfcResults; mcxActionApResults: McxActionApResults; mcxDefaultersResults: McxDefaultersResults; // 其他省略属性... } export interface CibilSfcResults { fnCheck: CibilSfc[]; fmCheck: CibilSfc[]; flCheck: CibilSfc[]; mlCheck: CibilSfc[]; fmlCheck: CibilSfc[]; panCheck: CibilSfc[]; remarks: string; resRemarks: string; }
报错信息(已翻译):
类型“string | number | boolean | Date | SebiList[] | UnList[] | UkSanctions[] | CibilSfcResults | McxActionApResults | ... 28 more ... | [...]”上不存在属性“resRemarks”。 类型“string”上不存在属性“resRemarks”。ts(2339)
解决方案
1. 类型守卫(推荐)
先定义一个类型守卫函数,用于判断当前值是否包含resRemarks属性:
function hasResRemarks(obj: unknown): obj is { resRemarks: string } { return typeof obj === 'object' && obj !== null && 'resRemarks' in obj; }
在业务代码中使用守卫做类型判断:
const targetObj = this.pmlaCheck[d.results as keyof PmlaCheck]; if (hasResRemarks(targetObj)) { // 此处TypeScript会自动推断targetObj包含resRemarks属性 const remarks = targetObj.resRemarks; // 执行后续逻辑 }
2. 精准类型断言
如果你能确定当前d.results对应的属性必然是包含resRemarks的子类型,可以直接做精准断言:
// 通用断言(适用于所有带resRemarks的子接口) const remarks = (this.pmlaCheck[d.results as keyof PmlaCheck] as { resRemarks: string }).resRemarks; // 针对特定子接口的断言(更精准) const remarks = (this.pmlaCheck[d.results as keyof PmlaCheck] as CibilSfcResults).resRemarks;
3. 重构接口定义优化类型约束
如果多个子接口都包含resRemarks和remarks属性,先提取共享接口:
// 定义共享接口 export interface HasResRemarks { resRemarks: string; remarks: string; } // 修改子接口继承共享接口 export interface CibilSfcResults extends HasResRemarks { fnCheck: CibilSfc[]; fmCheck: CibilSfc[]; flCheck: CibilSfc[]; mlCheck: CibilSfc[]; fmlCheck: CibilSfc[]; panCheck: CibilSfc[]; } // 其他包含resRemarks的子接口同理继承HasResRemarks
然后筛选出PmlaCheck中属于HasResRemarks类型的键:
type PmlaCheckKeysWithResRemarks = { [K in keyof PmlaCheck]: PmlaCheck[K] extends HasResRemarks ? K : never; }[keyof PmlaCheck];
后续代码中用这个类型做断言,就能直接访问resRemarks:
const targetKey = d.results as PmlaCheckKeysWithResRemarks; const remarks = this.pmlaCheck[targetKey].resRemarks; // 无类型报错
4. 可选链临时解决(不推荐长期使用)
如果允许resRemarks不存在时取默认值,可结合可选链和空值合并临时规避报错,但会丢失类型检查:
const remarks = (this.pmlaCheck[d.results as keyof PmlaCheck] as any)?.resRemarks ?? '';
内容的提问来源于stack exchange,提问作者hemant
相关产品推荐
相关产品推荐

