Skip to content

为什么函数返回布尔类型不会触发类型收窄? #370

@tofrankie

Description

@tofrankie

配图源自 Freepik

假设有一个判断字符串的函数:

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 返回真假,不会带来额外的类型信息,所以不会收窄。

类型收窄必须依赖签名(类型谓词)信息,而不是依赖函数实现。

附上类型收窄的方式:

  • typeof
  • instanceof
  • in 操作符
  • 判别联合(字面量字段)
  • 真值收窄(if 语句)
  • 等式收窄(===!== 等)
  • 类型谓词
  • 控制流分析(如赋值收窄等)
  • Exhaustive check + never

Metadata

Metadata

Assignees

No one assigned

    Labels

    20252025 年撰写TS与 Typescript 相关的文章

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions