TypeScript联合类型访问属性报错:为何不识别对象类型?
TypeScript联合类型访问属性报错问题解决
问题背景
我正在排查一段TypeScript代码的报错问题,搜索后未找到解决方法,希望得到技术指点。代码如下:
const latestTotal: number | { x: any; y: any; fillColor?: string | undefined; strokeColor?: string | undefined; meta?: any; goals?: any; } | [number, number | null] | [number, (number | null)[]] | null | undefined console.log(latestTotal.y) // 报错信息:Property 'y' does not exist on type 'number | { x: any; y: any; fillColor?: string | undefined; strokeColor?: string | undefined; meta?: any; goals?: any; } | [number, number | null] | [number, (number | null)[]]'. Property 'y' does not exist on type 'number'
该类型定义来自第三方库无法修改,我疑惑为何TypeScript不识别包含y属性的对象类型,反而提示number类型无此属性?
原因分析
TypeScript对联合类型的属性访问有严格限制:只有所有联合成员都拥有该属性时,才能直接访问。你的latestTotal包含number、数组、null/undefined这些没有y属性的类型,TypeScript无法确定当前值到底是哪种类型,所以会报错提醒你存在类型风险。
解决方法
必须通过类型守卫缩小类型范围,让TypeScript确认当前值是包含y的对象类型,再访问属性。以下是几种可行方案:
方案1:自定义类型守卫函数
// 定义类型谓词,判断是否为目标对象类型 function isYObject(val: typeof latestTotal): val is { x: any; y: any; fillColor?: string; strokeColor?: string; meta?: any; goals?: any; } { return typeof val === 'object' && val !== null && 'y' in val; } // 使用类型守卫 if (isYObject(latestTotal)) { console.log(latestTotal.y); // 此处TypeScript已确认类型,无报错 }
方案2:直接进行类型检查
// 排除number、数组、null/undefined类型 if (latestTotal !== null && typeof latestTotal === 'object' && !Array.isArray(latestTotal)) { console.log(latestTotal.y); // TypeScript会自动推断为目标对象类型 }
方案3:类型断言(谨慎使用)
如果你能100%确定当前场景下latestTotal就是包含y的对象,可以用类型断言强制转换(不推荐,若类型不符会导致运行时错误):
console.log((latestTotal as { y: any }).y);
内容的提问来源于stack exchange,提问作者Shan Robertson
相关产品推荐
相关产品推荐

