如何访问合并后的两个不同TypeScript对象数组中的非公共属性?
解决TypeScript合并异构数组后访问非公共属性的类型报错问题
问题场景
现有两个结构相似但带有非公共属性的TypeScript对象数组:
const objArr1: { commonProperty: string; ABC: string }[] = [ { commonProperty: "I am common", ABC: "I am different in object 1", }, { commonProperty: "I am common", ABC: "I am different in object 1", }, ] const objArr2: { commonProperty: string; XYZ: string }[] = [ { commonProperty: "I am common", XYZ: "I am different in object 2", }, { commonProperty: "I am common", XYZ: "I am different in object 2", }, ]
合并数组后直接访问非公共属性会触发TypeScript类型报错,因为TypeScript无法确定当前对象是否包含对应属性:
[...objArr1, ...objArr2].forEach(obj => { obj.commonProperty // 无错误 obj.ABC // TypeScript报错 obj.XYZ // TypeScript再次报错 })
以下是无需使用类型断言或any的解决方案:
方案1:使用in操作符类型守卫
利用TypeScript对in操作符的类型推断能力,在代码块内缩小对象的类型范围,安全访问对应属性:
[...objArr1, ...objArr2].forEach(obj => { console.log(obj.commonProperty); if ('ABC' in obj) { // 此处TypeScript推断obj为objArr1的元素类型 console.log(obj.ABC); } if ('XYZ' in obj) { // 此处TypeScript推断obj为objArr2的元素类型 console.log(obj.XYZ); } });
方案2:明确联合类型并细化分支判断
先定义清晰的联合类型,再结合in操作符做排他性判断,让TypeScript精准推断每个分支的类型:
// 定义独立类型别名 type TypeWithABC = { commonProperty: string; ABC: string }; type TypeWithXYZ = { commonProperty: string; XYZ: string }; type CombinedType = TypeWithABC | TypeWithXYZ; // 指定合并后数组的类型 const combinedArray: CombinedType[] = [...objArr1, ...objArr2]; combinedArray.forEach(obj => { console.log(obj.commonProperty); if ('ABC' in obj) { console.log(obj.ABC); } else { // 排除TypeWithABC后,TypeScript自动推断obj为TypeWithXYZ console.log(obj.XYZ); } });
方案3:使用判别式联合(推荐,若可修改原始类型)
给原始对象添加一个字面量类型的判别属性(如type),让TypeScript通过该属性快速区分对象类型,代码可读性和安全性更高:
// 定义带判别属性的联合类型 type TypeA = { type: 'A'; commonProperty: string; ABC: string }; type TypeB = { type: 'B'; commonProperty: string; XYZ: string }; // 修改原始数组的类型与内容 const objArr1: TypeA[] = [ { type: 'A', commonProperty: "I am common", ABC: "I am different in object 1" }, { type: 'A', commonProperty: "I am common", ABC: "I am different in object 1" }, ]; const objArr2: TypeB[] = [ { type: 'B', commonProperty: "I am common", XYZ: "I am different in object 2" }, { type: 'B', commonProperty: "I am common", XYZ: "I am different in object 2" }, ]; [...objArr1, ...objArr2].forEach(obj => { console.log(obj.commonProperty); if (obj.type === 'A') { console.log(obj.ABC); } else { console.log(obj.XYZ); } });
内容的提问来源于stack exchange,提问作者Prav
相关产品推荐
相关产品推荐

