You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
}

关键改动说明:

  1. 新增泛型K来捕获传入的键名类型,确保TypeScript能明确知道要检查的键是什么。
  2. 类型谓词改为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 09:57:03