TypeScript自定义类型谓词函数未按预期工作,求解析原因
问题原因分析
你遇到的问题核心在于泛型T的推断和keyof T的行为:
- 当
entry通过typeof entry === 'object'缩小为object类型后,调用objectHasKey(entry, 'someProperty')时,TypeScript会把泛型T推断为object类型。 - 而
keyof object的结果是never(因为object是所有非原始类型的顶层类型,没有明确的公共属性),这意味着你的类型谓词key is keyof T等价于key is never——这完全起不到缩小entry类型的作用,TypeScript依然认为entry是object类型,自然无法识别someProperty属性。
解决方案
修改类型谓词函数,让它能动态将对象类型缩小为包含指定键的结构,而不是依赖keyof T:
export function objectHasKey<T extends object, K extends PropertyKey>( obj: T, key: K, includeKeysFromPrototype: boolean = false ): obj is T & Record<K, unknown> { return includeKeysFromPrototype ? key in obj : Object.prototype.hasOwnProperty.call(obj, key); }
关键改动说明:
- 新增泛型
K来捕获传入的键名类型,确保TypeScript能明确知道要检查的键是什么。 - 类型谓词改为
obj is T & Record<K, unknown>,表示如果函数返回true,则obj的类型是原类型T加上包含键K的记录类型(unknown表示属性值类型不确定,你也可以根据需要改成更具体的类型)。
修正后的测试代码
注意还要加上entry !== null的判断(因为typeof null === 'object',避免运行时错误):
let entry: unknown = { someProperty: '123' } // (1) 符合预期 -> TS2339: Property 'someProperty' does not exist on type 'unknown' console.log(entry.someProperty) if (typeof entry === 'object' && entry !== null && objectHasKey(entry, 'someProperty')) { // 现在不会报错,TypeScript已识别entry包含someProperty属性 console.log(entry.someProperty) }
内容的提问来源于stack exchange,提问作者Thijmen
相关产品推荐
相关产品推荐

