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 里对必备属性就是编译错误。