TypeScript中如何对unknown类型对象做类型收缩并访问属性
报错根本原因
你原写法报错是因为 TypeScript 的类型收缩规则限制,in 操作符目前无法给基础 object 类型追加属性标记。unknown 经过 typeof result === 'object' && result !== null 收缩后只能得到 object 类型,该类型默认没有任何已知属性,所以直接访问 movieName 就会触发类型错误。
方案1:自定义类型守卫(最推荐,类型安全最高)
写专用的类型判断函数,用类型谓词明确告知TS判断通过后的类型,逻辑可复用,不需要额外写后续断言:
// 定义类型守卫 function hasMovieName(obj: unknown): obj is { movieName: string } { return ( typeof obj === 'object' && obj !== null && 'movieName' in obj && typeof (obj as Record<string, unknown>).movieName === 'string' ) } const result: unknown = { movieName: "test", }; if (hasMovieName(result)) { // 这里直接访问result.movieName不会报错,TS已经自动识别到类型 console.log(result.movieName) }
方案2:访问属性时临时断言
如果不想单独写守卫函数,可以在判断属性类型的位置临时做断言处理:
const result: unknown = { movieName: "test", }; if ( typeof result === "object" && result !== null && "movieName" in result && typeof (result as Record<string, unknown>).movieName === "string" ) { // 后续使用前再做一次断言即可 const validResult = result as { movieName: string } console.log(validResult.movieName) }
方案3:提前收缩为Record<string, unknown>
如果可以接受先做一次断言把unknown转成松散的键值对类型,后续判断逻辑会更简洁:
const result: unknown = { movieName: "test", }; // 先做基础校验+类型转换,不符合要求的分支提前退出 if (typeof result !== 'object' || result === null) { throw new Error('result格式错误') } const validResult = result as Record<string, unknown> if (typeof validResult.movieName === 'string') { // 这里直接访问属性不会报错 console.log(validResult.movieName) }
内容的提问来源于stack exchange,提问作者Diesel
相关产品推荐
相关产品推荐

