TypeScript 基础 — 类型谓词

TypeScript 中的类型谓词(type predicates)可以帮助您根据条件缩小类型范围。它与 type guards 类似,但在函数上工作。如果函数返回 true,则将参数的类型更改为更有用的类型。

让我们从一个基本的例子开始。假设您有一个函数,用于检查某个值是否为 string 类型:

function isString(s) {
  return typeof s === 'string'
}

在另一个函数中使用 isString 函数:

function toUpperCase(x: unknown) {
  if(isString(x)) {
    x.toUpperCase() // x 的类型 unknown
  }
}

TypeScript 会抛出一个错误。我们可以确定此时 x 的类型是 string。但是,由于验证封装在函数中,所以 x 的类型不会改变(与 type guard 相反)。

让我们显式地告诉 TypeScript,如果 isString 的值为 true,则形参的类型是一个字符串:

function isString(s): s is string {
  return typeof s === 'string'
}

TypeScript 现在知道我们在 toUpperCase 函数中处理的是字符串。

function toUpperCase(x: unknown) {
  if(isString(x)) {
    x.toUpperCase() // ✅ x是字符串
  }
}

缩小集合范围

这不仅可以帮助您查找未知类型或多个类型,还可以缩小类型内的集合。我们来做一个掷骰子的程序。每次你掷出一个六,你就赢了。

function pipsAreValid(pips: number) {
  // 我们检查每个离散值,因为数字也可以是介于 1 和 2 之间的值。
  return (
    pips === 1 ||
    pips === 2 ||
    pips === 3 ||
    pips === 4 ||
    pips === 5 ||
    pips === 6
  )
}

function evalThrow(count: number) {
  if (pipsAreValid(count)) {
    switch (count) {
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
        console.log('Oh!')
        break
      case 6:
        console.log('赢了!')
        break
      case 7:
        // TypeScript 在这里没有报错,尽管 count 不可能是 7
        console.log('这行不通!')
        break
    }
  }
}

该程序一开始看起来不错,但从类型的角度来看有一些问题:countnumber 类型。这可以作为输入参数。我们马上验证 count 是一个介于 1 和 6 之间的数字。一旦我们验证了这一点,count 就不再是任何数字了。它被缩小为六个值的离散集合。

所以从 switch 语句开始,我的类型已经错了!为了避免任何进一步的复杂情况,让我们使用联合类型将数字集缩小到这六个离散值:

type Dice = 1 | 2 | 3 | 4 | 5 | 6

function pipsAreValid(pips: number): pips is Dice {
  return (
    pips === 1 ||
    pips === 2 ||
    pips === 3 ||
    pips === 4 ||
    pips === 5 ||
    pips === 6
  )
}

function evalThrow(count: number) {
  if (pipsAreValid(count)) {
    switch (count) {
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
        console.log('Oh!')
        break
      case 6:
        console.log('赢了!')
        break
      case 7:
        // error:7 不是联合类型的
        // 类型 7 不可与类型 Dice 进行比较
        console.log('这行不通!')
        break
    }
  }
}

这对我们来说更为安全。当然,这种“类型转换”可以是任何有助于增强应用程序的东西。即使验证了复杂的对象,也可以将参数缩小到特定的类型,并确保它们与代码的其余部分保持一致。非常有用,尤其是当你依赖很多函数时。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值