TypeScript全解:交叉类型

2023-06-09  本文已影响0人  littleyu

交叉类型(Intersection Types)(交集)

type A = string & number

很显然 A 的结果是 never,因为字符串和数字是两种完全不同的东西,所以一般交叉类型,我们不会用在普通类上

type 有左手的人 = {
  left: string;
}
type 有右手的人 = {
  right: string;
}
type C = 有左手的人 | 有右手的人
type D = 有左手的人 & 有右手的人

以上的 C、D 类型用一张图表示:

思考"有左手的人" 可以有"右手"吗?

type 有左手的人 = {
  left: string;
}

const a: 有左手的人 = {
  left: '左手',
  right: '右手', // TODO: 这里会有报错
}

很显然,这里的代码报错了,但是从逻辑上来讲,"有左手的人" 难道不能有"右手"吗?,再来看接下来的栗子:

type 有左手的人 = {
  left: string;
}

const b = {
  left: '左手',
  right: '右手',
}

const a: 有左手的人 = b

神奇的是,竟然不报错了,这就是 ts 很奇怪的地方,初始化的时候不能有多余的东西

接口也能交集

interface 有左手的人 {
  left: string;
}
interface 有右手的人 {
  right: string;
}

type 完整的手 = 有左手的人 & 有右手的人

特殊情况

普通对象

type Person = {
  name: string;
  age: number;
  id: string;
}
type User = Person & {
  id : number; // TODO: 注意:这里并没有报错
  email: string;
}

const a: User = {
  id: 1, // TODO: 这里报错了,并且提示类型为 never,
  name: 'Jack',
  email: 'qq.com',
}

但是稍微改造一点,还有更特殊的情况


type Person = {
  name: string;
  age: number;
  id: 'A'; // TODO: 这里更具体了
}
type User = Person & {
  id : 'B'; // TODO: 这里更具体了
  email: string;
}

const a: User = { // TODO: 这里直接提示 User 类型为 never,
  id: 1,
  name: 'Jack',
  email: 'qq.com',
}

这就很难解释了,直接记住这种情况把~

函数

type A = {
  method: (n: number) => void
}
type B = {
  method: (n: string) => void
}

const b: B = {
  method: n => { // TODO: 没有报错
    console.log(n)
  }
}

可以发现当为函数的时候这里没有报错,且参数 n 的类型为 string | number,

一个接受参数类型为 number 的方法,一个接受参数类型为 string 的方法,这两个方法有没有交集呢?到目前来看已经很难想清楚了,明明是交集,怎么会得出并集!我们再来验证一下:

type F1 = (n: number) => void
type F2 = (n: string) => void

type X = F1 & F2

const x: X = (n) => {
  console.log(n)
}

也没有报错,且参数 n 的类型为 string | number

也就是说,如果我们再在做两个对象交集的时候,遇到 key 的名字冲突的时候,那么他会对这个属性进行交集,且递归的交。

但是特殊在函数这里,函数的交集,会得到参数的并集,说实话我又不是很理解了,没办法按实践的结果来死记硬背把~

上一篇 下一篇

猜你喜欢

热点阅读