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

TypeScript如何编写可校验接口属性类型的类型守卫

报错原因

这个报错的核心问题出在对象判断逻辑和类型收窄顺序上:

  • value instanceof Object 不是可靠的对象校验逻辑:Object.create(null)生成的无原型对象、跨iframe/Realm创建的纯对象都会被判定为false,不符合「传入值为对象类型」的校验需求;同时TypeScript对unknown类型做instanceof Object收窄时,和后续in操作符的收窄逻辑存在冲突,会导致in判断后value被意外推导为never类型,自然无法访问任何属性。
  • 没有先将unknown类型收窄为明确的object类型就直接做属性存在性校验,TS无法推导该值上允许挂载自定义属性。

正确实现

按照类型收窄的顺序依次完成三层校验即可,推荐用更可靠的逻辑替代instanceof Object:

interface Person {
  name: string;
}

const isPerson = (value: unknown): value is Person => {
  // 第一步:校验为非空对象,排除原始值、null、undefined
  if (typeof value !== 'object' || value === null) {
    return false
  }
  // 此处TS已将value收窄为object类型,可安全使用in操作符
  // 第二步:校验存在name属性
  if (!('name' in value)) {
    return false
  }
  // 此处TS已推导value包含类型为unknown的name属性,可安全访问
  // 第三步:校验name属性为string类型
  return typeof value.name === 'string'
}

如果偏好单行箭头函数的写法,只要调整判断顺序、替换不可靠的instanceof判断也可正常运行:

const isPerson = (value: unknown): value is Person => (
  typeof value === 'object'
  && value !== null
  && 'name' in value
  && typeof value.name === 'string'
)

逻辑说明

TypeScript会跟随判断逻辑自动做类型收窄:

  1. 经过typeof value === 'object' && value !== null判断后,value类型从unknown收窄为object
  2. 经过'name' in value判断后,value类型收窄为object & { name: unknown },访问value.name不会触发类型错误
  3. 最后通过typeof value.name === 'string'校验后,完全匹配Person接口的结构,类型守卫生效。

如果需要校验更复杂的嵌套接口,沿用逐层收窄的逻辑即可,不需要额外加类型断言。

内容的提问来源于stack exchange,提问作者slifty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 07:54:21