TypeScript如何判断未知对象是否包含指定属性?
TypeScript判断unknown类型对象是否包含指定属性的问题解析与简化方案
为什么双重检查后TypeScript仍不识别code属性?
- 当
typeof error === 'object'后,error类型被收窄为object | null,error && ...排除null后剩余object类型。 'code' in error理论上能收窄类型,但TypeScript对in操作符的类型收窄逻辑在与hasOwnProperty结合时,无法直接推断出对象必然拥有该属性——因为hasOwnProperty是通用方法,TS无法通过这个调用自动完成类型收窄。- 此外,
object类型在TS中是宽泛的顶层类型,即使知道有某个属性存在,TS也不会自动为其添加属性类型定义,必须通过类型断言或自定义类型守卫来明确。
简化实现方案
方案1:直接使用类型断言+类型谓词
不需要额外声明中间类型变量,直接在判断中做断言:
export function isMySpecificError(error: unknown): error is { code: string } { if (typeof error !== 'object' || error === null) return false; // 断言为包含可选code属性的对象 const err = error as { code?: unknown }; return ( typeof err.code === 'string' && err.code.startsWith('someErrorCodeValue') ); }
如果需要严格检查code是对象自身属性而非继承属性,可添加hasOwnProperty判断:
export function isMySpecificError(error: unknown): error is { code: string } { if (typeof error !== 'object' || error === null) return false; const err = error as { code?: unknown }; return ( Object.prototype.hasOwnProperty.call(err, 'code') && typeof err.code === 'string' && err.code.startsWith('someErrorCodeValue') ); }
方案2:自定义通用属性检查类型守卫
创建一个通用的hasOwnProperty类型守卫函数,帮助TS自动完成类型收窄,后续可复用:
// 通用类型守卫:检查对象是否拥有指定自身属性 function hasOwnProperty<T extends object, K extends PropertyKey>( obj: T, key: K ): obj is T & Record<K, unknown> { return Object.prototype.hasOwnProperty.call(obj, key); } export function isMySpecificError(error: unknown): error is { code: string } { if (typeof error !== 'object' || error === null) return false; // 此时TS会自动收窄error类型为包含code属性的对象 if (!hasOwnProperty(error, 'code')) return false; return typeof error.code === 'string' && error.code.startsWith('someErrorCodeValue'); }
其他判断未知对象属性的方式
- 利用
in操作符配合类型谓词:直接在返回条件中使用'code' in error,结合类型断言完成检查,适合简单场景。 - 使用
Object.hasOwn:ES2022新增的Object.hasOwn方法替代hasOwnProperty,语义更清晰,同样可配合类型守卫使用。 - 类实例检查:如果目标对象是某个类的实例,可使用
instanceof操作符,但仅适用于已知类的场景,不适用于匿名对象。
内容的提问来源于stack exchange,提问作者203equL
相关产品推荐
相关产品推荐

