第六章 TypeScript高级类型(交叉类型,联合类型,类型保护)

在这里插入图片描述

一、交叉类型( Intersection Types )

  • 这个就和我们运算符里面的 与( && ) 是一样的,既要 … 又要 … 还要 … O(∩_∩)O~
  • 使用 & 作为交叉符号
  • 一个小栗子
// 对象接口1
interface One {
  name: string
  age: number
}

// 对象接口2
interface Two {
  gender: string
  classRoom: number
}

// 简单准备一个函数
function combine(o1: One, o2: Two) {
  const result = {
    ...o1,
    ...o2
  }
  return result
}
  • 我们看到,一个简单的功能函数就是把两个对象合并到一个对象
  • 我们给到参数进行了限制,但是返回值咋办呢 ?
  • 这个时候就可以用到交叉类型了
function combine(o1: One, o2: Two): One & Two {
  const result = {
    ...o1,
    ...o2
  }
  return result
}
  • 这样的话,就是返回值既要满足 One 的接口要求,也要满足 Two 的接口要求

image.png
在这里插入图片描述

  • 你看,少了任何一个都不行
  • 其实就是 与 的关系 O(∩_∩)O~

二、联合类型(Union Types)

  • 这个就和我们运算符里面的 或( || ) 是一样的,哪一个都行 O(∩_∩)O~
  • 使用 | 作为联合符号
  • 很多时候,我们在定义一些内容的时候,可能需要使用到多种都可以,不管是类型,包括字面量约束也是一样的
let foo: number | string = 100
foo = 'hello world'
foo = 200
  • 我们给 foo 赋值为 number 类型或者 string 类型都是可以的
  • 字面量也是可以联合的
let color: 'yellow' | 'blue' | 'orange'

image.png

  • 这就是联合类型

三、类型保护( Type Guards )

  • 先来看一个案例
interface One {
  name: string
  sayHi(): void
}
interface Two {
  name: string
  play(): void
}

const user1: One = { 
  name: 'Jack', 
  sayHi: () => console.log('hello world') 
}
const user2: Two = { 
  name: 'Rose', 
  play: () => console.log('basketball')
}

function util(user: One | Two): void {
  console.log(user.name)
  user.sayHi()
  user.play()
}

util(user1)
util(user2)

在这里插入图片描述

  • 我们发现里面报错了
  • 这是因为,两个接口里面都有 name 属性,所以调用 name 属性没问题
  • 但是你得 user 不确定是 One 还是 Two 类型
  • 调用 sayHi 的活,如果是 Two 类型就没有,就会提示错误
  • 调用 play 的话,如果是 One 类型就没有,就会提示错误
  • 一旦联合以后,我们就只能访问两个类型公共的数据
  • 可能有同学想到判断一下不就好了
function util(user: One | Two): void {
  console.log(user.name)
  if (user.sayHi) {
    user.sayHi()
  } else {
    user.play()
  }
}

在这里插入图片描述

  • 依旧是一个提示错误的状态
  • 这个时候就需要用到断言来对类型进行一次保护
function util(user: One | Two): void {

  console.log(user.name)
  if ((user as One).sayHi) {
    (user as One).sayHi()
  } else {
    (user as Two).play()
  }

}
  • 当我在访问一些非公共属性的时候,进行一下断言,确定它一定会有这个属性我才访问
  • 断言也有另外一种写法,也是可以的
function util(user: One | Two): void {
  console.log(user.name)
  if ((<One>user).sayHi) {
    (<One>user).sayHi()
  } else {
    (<Two>user).play()
  }
}
  • 这两种书写方式是一样的,都是可以实现类型保护

自定义类型保护

  • 通过刚才的案例,我们发现可以解决问题,但是很麻烦
  • 因为要不停的写一些断言来验证一下

image.png

  • 随着后面的使用,用的越多,需要写断言的地方就越多,少一个都不行
  • 这个时候,我们就可以自己写一个类型验证函数,作用就是专门用于检查类型
  • 先来定义一个类型验证函数
function isOne(pet: One | Two): pet is One {
  return (<One>pet).sayHi !== undefined
}
  • 这里的返回值设置,pet is One 是 TS 的语法,表示 pet 是不是 One 这个类型,结果必然是一个布尔值,true 或者 false
  • 注意 : 这里的 pet 必须是该函数的形参才可以哦
  • 后面使用的时候,直接使用 isOne 函数就可以了哦
function util(user: One | Two): void {
  if (isOne(user)) {
    user.sayHi()
  } else {
    user.play()
  }
}
  • 20
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杨树林er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值