in in 操作符收窄

最后更新:2026-10-22

in in 操作符收窄

in 操作符检查某个属性名是否存在于对象上,TypeScript 借此把联合类型收窄到"拥有该属性"的那个成员。当联合的各成员没有共同字段可判别、又是接口(不能用 instanceof)时,in 是最顺手的结构区分手段。

分组收窄与断言
类型操作符
严格模式不需要

ℹ️ 说明 编辑器将 TypeScript 转译为 JavaScript 后运行(不做类型检查);类型检查结果见示例 Output。

📝 语法

interface Bird { fly: () => void }
interface Fish { swim: () => void }

function move(animal: Bird | Fish) {
  if ("swim" in animal) {
    animal.swim();   // 收窄为 Fish
  } else {
    animal.fly();    // 收窄为 Bird
  }
}

⚙️ 参数

"key" in obj运行时检查 key 是否是 obj 的属性(含原型链上的),返回 boolean;TS 同时把 obj 收窄到含该属性的联合成员

返回值:in 表达式返回 boolean;收窄效果发生在编译期,依赖联合成员之间的属性互斥(有/没有某个属性)。

▶ 示例

修改下面的代码,点击试一试查看转译运行结果:

输出:

bubble...
it swims
flap!
it flies

(转译后运行输出;animal.swim() 能通过类型检查,是因为 in 收窄已把 animal 定为 Fish——收窄由 tsc 静态保证,运行时只看到值)

💡 要点

ℹ️ 说明 in 检查的是"属性存在与否",包括原型链上继承来的属性。对 plain object 来说 toString、constructor 这类内置属性也在,所以检查请用业务字段名。
⚠️ 注意 in 收窄依赖"属性互斥":如果两个成员都有同名字段(只是类型不同),in 只能帮上有限忙。这种场景应改用可辨识联合(判别字段取不同的字面量值)。
💡 提示 in 也是映射类型的核心语法([K in keyof T]),但那是类型层用法;本条讲的 in 是运行时操作符 + 编译期收窄。
更多案例即将上线。

📚 相关教程

❓ 常见问题

Q in 收窄和可辨识联合该怎么选?
A 能给每个成员设计一个互不相同的字面量字段(如 type/status/kind)就用可辨识联合,更清晰也支持穷尽检查;联合来自第三方、没有判别字段时,用 in 按结构区分。
Q 可选属性会被 in 误判吗?
A 会。可选属性 flag?: boolean 在对象上可能实际不存在,flag in obj 为 false 不代表它属于另一个成员。用 in 前确认该属性在每个成员上是"必有"或"必无"。
Q delete 掉属性后 in 还能正确收窄吗?
A 能。delete obj.key 后 in 的运行时结果就是 false,TS 会收窄到不含该属性的成员。但运行时类型与声明类型可能已经不符——delete 本身在严格 TS 里对必备属性就是编译错误。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏