x is T 自定义类型守卫与断言函数

最后更新:2026-10-22

x is T 自定义类型守卫与断言函数

内置守卫(typeof/instanceof/in)不够用时,可以自己写类型守卫函数:返回值写成 x is T(类型谓词),TS 就会在函数返回 true 的分支里把 x 收窄成 T。它的兄弟是断言函数(asserts x is T),不返回布尔值而是直接抛错。

分组收窄与断言
类型语法
严格模式不需要

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

📝 语法

// 类型谓词:返回 true 时 x 被收窄为 T
function isFoo(x: unknown): x is Foo {
  return typeof x === "object" && x !== null && "foo" in x;
}

// 断言函数:不通过就抛错,通过后 x 被视为 T
function assertFoo(x: unknown): asserts x is Foo {
  if (!isFoo(x)) throw new Error("not a Foo");
}

⚙️ 参数

x is T类型谓词返回类型:参数名 is 目标类型。函数体里必须做真实的运行时检查
asserts x is T断言函数返回类型:校验失败应抛异常;调用点之后的代码把 x 视为 T

返回值:is 谓词函数运行时就是普通布尔函数;收窄效果发生在编译期。asserts 函数运行时无返回值(void),失败靠 throw。

▶ 示例

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

输出:

failed: 404
data: x,y

(转译后运行输出;isFailure 返回 true 后 res 被收窄为 ApiError,res.data 能通过类型检查——收窄由 tsc 静态保证,运行时只看到值)

💡 要点

ℹ️ 说明 x is T 只改变编译器的看法,运行时它就是一个普通函数。函数体里的检查必须与声明的 T 一致,否则等于对编译器撒谎。
⚠️ 注意 守卫写错不会被编译器发现:比如声明 res is ApiError 却检查了别的字段,错误类型会静默流入分支,运行时才炸。守卫逻辑要经过测试。
💡 提示 参数类型写 unknown 而不是 any,能让守卫强制完成全部检查;unknown 上不做收窄不能操作,倒逼你写出完整校验逻辑。
更多案例即将上线。

📚 相关教程

❓ 常见问题

Q x is T 和直接返回 boolean 有什么区别?
A 返回 boolean 时编译器不知道 true 意味着什么,调用后 x 的类型不变;返回 x is T 时,true 分支里 x 被收窄为 T。谓词只改类型,不增加运行时开销。
Q 什么时候用 asserts 版本而不是 is 版本?
A 数据非法就该立刻终止(配置加载、测试断言、环境校验)用 asserts x is T——失败抛错,后面的代码放心用;需要"二选一"分支处理(成功走 A 失败走 B)用 is。
Q TS 4.4 之后还有更省事的写法吗?
A 有:TS 4.4 起可以直接提取 const isFailure = res.ok === false 这类布尔值做自动收窄(aliased conditions),也可以把 const x: boolean = ... 的判断间接复用。不过封装成具名守卫函数仍是复用性最好的做法。
Web-Tutorial.com

Web-Tutorial 技术团队

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

100%

🙏 帮我们做得更好

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

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