-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Labels
Description
假设有一个判断字符串的函数:
function isStr(value: unknown) {
return typeof value === 'string'
}TS 会自动推断返回类型为 boolean。
let value: number | string = Math.random() > 0.5 ? 'hello' : 1
if (isStr(value)) {
// ❌ Property 'length' does not exist on type 'string | number'.
value.length
}但使用时会有问题,可见 TS 并没有做类型收窄。
解决方法也简单,使用类型谓词(Type Predicates)即可:
function isStr(value: unknown): value is string {
return typeof value === 'string'
}Note
注意,自 TypeScript 5.5 起支持推断类型谓词,无需显示指定。
类型谓词用于描述函数的返回值类型。这里 value is string 并不是返回类型,而是告诉 TS 如果函数返回 true,那么参数 value 一定是 string 类型。换句话说,当函数返回 true 时,告诉 TS 编译器参数 value 的类型应该被收窄为 string。
为什么函数返回布尔类型不会触发类型收窄?
因为 TS 的类型系统是静态的,编译时它不会去分析函数的实现,只是根据签名(返回类型)来决定能不能做收窄。只告诉 TS 返回真假,不会带来额外的类型信息,所以不会收窄。
类型收窄必须依赖签名(类型谓词)信息,而不是依赖函数实现。
附上类型收窄的方式:
typeofinstanceofin操作符- 判别联合(字面量字段)
- 真值收窄(
if语句) - 等式收窄(
===、!==等) - 类型谓词
- 控制流分析(如赋值收窄等)
- Exhaustive check + never
