TypeScript自定义联合类型访问对象属性提示属性不存在报错
TypeScript联合类型访问分支属性报错解决
问题复现
当你用原始类型和对象类型组合成联合类型时,直接访问仅存在于对象分支上的属性,TypeScript会抛出类型错误,因为TS无法确认当前变量的实际类型属于对象分支,不允许访问不存在于所有联合成员上的属性。
相关类型定义:
export type FileTypePrimitive = string | null; export type FileType = { name: string; url: string }; export type GenratedKey = FileType| FileTypePrimitive;
触发报错的代码:
const keysToSend = genratedFileKeys() // 返回值类型为GenratedKey const url = keysToSend.name ? keysToSend.url : keysToSend; // 类型错误:Property 'name' does not exist on type 'string | FileType | null'
解决方法
核心逻辑是先做类型收窄,让TS能够确认当前变量属于FileType对象分支后,再访问对应属性,常用实现有三种:
- 方法1:通过typeof筛除原始类型
联合类型中除FileType外的成员都是原始类型(string/null),可以通过typeof判断值为非null的对象后再访问属性:const keysToSend = genratedFileKeys(); // 注意typeof null的返回值也是'object',必须额外判空 const url = typeof keysToSend === 'object' && keysToSend !== null ? keysToSend.url : keysToSend; - 方法2:用in操作符判断属性存在
直接判断目标属性是否存在于当前值上,TS会自动完成类型收窄,写法更简洁:
如果使用TS 4.9以下版本,const keysToSend = genratedFileKeys(); const url = 'name' in keysToSend ? keysToSend.url : keysToSend;in操作符无法自动处理null值,补一层非空判断即可:const url = keysToSend != null && 'name' in keysToSend ? keysToSend.url : keysToSend; - 方法3:封装可复用类型守卫
如果该判断逻辑在多处使用,可以封装为类型守卫函数,复用性更强:function isFileType(val: GenratedKey): val is FileType { return typeof val === 'object' && val !== null && 'name' in val && 'url' in val; } // 业务代码中使用 const keysToSend = genratedFileKeys(); const url = isFileType(keysToSend) ? keysToSend.url : keysToSend;
内容的提问来源于stack exchange,提问作者NicoleZ
相关产品推荐
相关产品推荐

