Skip to content

交叉(交集)类型&

交叉类型和符号的意思相似,就表示 and 的意思,把&相交的组合起来,值需要全部满足相交组合的类型

javascript
type Student = { name: string, score: number };
type Teacher = { name: string, age: number, subject: string };
type User = Student & Teacher;
const user1: User = { name: "jack", age: 18, subject: "math" }; // error 缺少属性"score"

虽然有时候口头上经常会说交集类型,但是在教学的时候,我并不是太喜欢把&符号称为交集,叫做交叉应该更容易理解一些,不容易给大家造成思想误区。

就拿上面的类型来说,A&B ----> 一说交集应该是,type C = {name:string} 才对啊,最后得到的好像是我记忆中数学的联合类型啊?不用对你的记忆怀疑,你的记忆是对的,你可以把锅丢给翻译

为了便于理解,你可以这样想:C 既符合 A 也符合 B,所以是 A 和 B 的“交叉”,有了这样的理解,下面出现的一些情况,我们才能更好的理解

相比联合类型,交叉类型的范围就没有那么广泛了,因为你不可能把具体的值使用&组合,这样意义也就混乱了

javascript
type Width = number & string; // never类型

numberstring 没有什么交集,因此根本无法给变量赋值,交叉类型始终交叉的是类型,类型字面量或者基础类型,在做类型交叉的时候没有任何意义,因此得到的结果是 never。具体类型 never 类型的使用我们后面讲解

其实,对象字面量类型一样会有这样的效果

typescript
type P = {
  name: string;
  sex: string;
};
type T = {
  name: string;
  age: number;
};
type PT = P & T;

const a: PT = {
  name: "jack",
  sex: "男",
  age: 11,
};

如果有同名属性,并且类型一样,就会直接合并,但是如果类型不一样呢?

diff
type P = {
  name: string
  sex: string
}
type T = {
+  name: number
  age:number
}
type PT = P & T

const a: PT = {
+  name: 'jack', // error 不能将类型“string”分配给类型“never”
  sex:'男',
  age:11
}

不过我们可以使用交集类型的特性,达到一些我们需要的效果。

比如,我们可能有一个联合类型,在实际开发中,可能这个联合类型我们并不知道有哪些,或者可能这个联合类型直接赋值给另外一个类型的时候会报错,我们可以使用&运算符对其进行约束

typescript
type params = string | number | boolean;
type pt = params & string;

当然我们现在代码很简单,只能简单模拟这个情况,讲到一些类型工具之后我们再来看一些复杂情况

比如,我们还能使用交叉类型来实现类似于继承的效果

javascript
type Goods = {
  id: number
  name: string
  price: number
}

type Cart = Goods & {
  count: number
}

type Order = Goods & {
  count: number
  totalPrice: number
}

const goods: Goods = {
  id: 1,
  name: 'goods',
  price: 100
}

const cart: Cart = {
  id: 1,
  name: 'goods',
  price: 100,
  count: 1
}

const order: Order = {
  id: 1,
  name: 'goods',
  price: 100,
  count: 1,
  totalPrice: 100
}