Last updated on Oct 6, 2022

类型查询操作符

在 TypeScript 中存在两种功能不同的 typeof 操作符。

  1. JavaScript 中用于检查变量类型的 typeof,对于基本类型(除了 null)都能返回正确的类型
  2. 除此之外,TypeScript 中还新增了用于类型查询的 typeof(Type Query Operation),用于返回一 TypeScript 类型
const str = 'Samuel'
const obj = { name: 'Samuel' }
const nullVar = null
const undefinedVar = undefined
const func = (input: string) => {
  return input.length > 10
}

type Str = typeof str // 'Samuel'
type Obj = typeof obj // { name: string; }
type Null = typeof nullVar // null
type Undefined = typeof undefinedVar // undefined
type Func = typeof func // (input: string) => boolean

除了可以在类型标注中使用 typeof,还能在工具类型中使用 typeof

const func = (input: string) => {
  return input.length > 10
}

type Func = typeof func // (input: string) => boolean

const func2: typeof func = (name: string) => {
  return name === 'Samuel'
}

// boolean
type FuncReturnType = ReturnType<typeof func>

大多数情况下,typeof 返回的类型是最窄的推导类型(即到字面量类型的级别

这两种 typeof 混用了怎么解决?

类型守卫(is)

TypeScript 提供了强大的类型推导能力,会随着代码逻辑不断尝试收窄类型,这就是类型的控制流分析(简单理解为:类型推导)

declare const strOrNumOrBool: string | number

if (typeof strOrNumOrBool === 'string') {
  // 一定是字符串
  strOrNumOrBool.charAt(1)
} else if (typeof strOrNumOrBool === 'number') {
  // 一定是数字
  strOrNumOrBool.toFixed()
} else {
  // 要是走到这里就说明有问题!
  const _exhaustiveCheck: never = strOrNumOrBool
  throw new Error(`Unknown input type: ${_exhaustiveCheck}`)
}

通过在 if 条件中的表达式进行了类型保护,从逻辑中进行类型地推导,再反过来让类型为逻辑提供保障。

但类型的控制流分析做不到跨函数上下文来进行类型的信息收集。