TypeScript中User | Record<string, never>联合类型键访问异常问题
解决方案
你的问题出在Record<string, never>的类型特性上:它通过索引签名声明了所有字符串键对应的值类型都是never,但TypeScript处理联合类型时,never会被其他类型“吸收”。比如User | Record<string, never>中,访问role时,TypeScript会认为User的role是有效类型,而Record<string, never>的role是never,最终联合类型会被简化为User['role'](即string),所以不会触发报错。
要实现你想要的效果——空对象类型访问role时直接报错,需要让空对象类型明确不包含role属性,且与User类型不兼容。这里有两种可靠的实现方式:
方式一:用唯一符号标记空对象
通过添加一个唯一的符号属性,让空对象类型与User彻底区分开,同时允许空对象{}赋值:
interface User { role: string; } // 定义唯一符号作为空对象的标记 const emptyObjMarker = Symbol('empty-object'); // 空对象类型:可选的符号属性,确保与User不兼容 type EmptyObject = { [emptyObjMarker]?: never }; // 最终的联合类型 type StateUser = User | EmptyObject; // 测试场景 const validUser: StateUser = { role: 'admin' }; validUser.role; // 正常,类型为string const emptyUser: StateUser = {}; emptyUser.role; // 触发报错:Property 'role' does not exist on type 'EmptyObject'.
方式二:明确禁止User的所有属性
通过映射类型定义一个不能拥有User任何属性的空对象类型,确保空对象{}符合要求,同时访问role会报错:
interface User { role: string; } // 定义空对象类型:User的所有属性都是可选的never类型(即不能存在这些属性) type EmptyObject = { [K in keyof User]?: never }; type StateUser = User | EmptyObject; // 测试场景 const validUser: StateUser = { role: 'admin' }; validUser.role; // 正常 const emptyUser: StateUser = {}; emptyUser.role; // 触发报错:Property 'role' does not exist on type 'EmptyObject'.
这两种方式都能让TypeScript正确识别联合类型的差异,在访问role时,若未通过类型收窄确认是User类型,就会触发你期望的属性不存在错误。
内容的提问来源于stack exchange,提问作者Thiago Pereira Maia
相关产品推荐
相关产品推荐

