| 内置守卫 |
|---|
| 收窄原始类型:string、number、boolean 等。 | if (typeof x === 'string') x.toUpperCase() |
| 收窄为类或可构造的实例。 | if (e instanceof Error) e.message |
| 通过检查值上是否存在某属性来收窄。 | if ('id' in obj) obj.id |
| 把任意值收窄为数组;把联合收窄到其数组成员。 | if (Array.isArray(x)) x.map(f) |
| 自定义守卫 |
|---|
| 返回值能收窄参数的谓词函数。 | function isUser(x): x is User { return !!x.id } |
| 谓词可以收窄为多个类型的联合,而不只是单个类型。 | function isKey(x): x is string | number |
| 交叉类型谓词保留输入类型并向其添加字段。 | function hasId(x): x is x & { id: string } |
| 断言函数,除非 x 是该类型,否则抛出异常。 | function assertUser(x): asserts x is User |
| 可辨识联合 |
|---|
| 通过共享的字面量字段用 switch 或 if 收窄联合。 | type E = { kind: 'a'; a: number } | { kind: 'b'; b: string } |
| 每个 case 收窄到联合的一个成员。 | switch (u.kind) { case 'a': u.a } |
| 当某属性只存在于一个成员时,收窄无标签的联合。 | if ('b' in u) u.b |
| 每个 case 是一个条件;命中的 case 收窄该值。 | switch (true) { case typeof x === 'string': } |
| default 分支赋值给 never,证明 switch 覆盖了所有情况。 | default: { const x: never = u } |
| 相等性与流程 |
|---|
| 相等检查后移除 null 和 undefined。 | if (x === null) return; x.toFixed() |
| 移除假值(0、''、null、undefined、NaN)。 | if (!x) return; // x is defined here |
| 链式属性为真值时证明基值存在。 | if (user?.active) user.name |
| 非空断言不做检查就移除 null 和 undefined。 | x!.toFixed(2) |
| 明确赋值断言:声明 x 在被读取之前会先赋值。 | let name!: string; init() |
| 收窄在分支内以及提前 return 之后都有效。 | if (!arr) return; arr.map(...) |
| 别名与延迟 |
|---|
| 保存检查结果的 const 布尔值在它被测试的任何地方都能收窄。 | const isStr = typeof x === 'string'; if (isStr) … |
| const 变量在捕获它的闭包内保持收窄。 | const s = get(); if (s) use(() => s.length) |
| 自 TS 5.4 起,let 或参数在最后一次赋值之后在闭包内保持收窄。 | let n: string | null = get(); if (n) use(() => n.length) |
| unknown 在守卫把它收窄为真实类型之前无法使用。 | if (typeof u === 'string') u.length |