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 = ... 的判断间接复用。不过封装成具名守卫函数仍是复用性最好的做法。