TS 中的类型运算:交叉类型

交叉类型(交集)

英文全称:intersection types

ts
type A = string & number;
//   ^-- never

交叉类型一般多用于对象,而不用于简单类型

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

const b = { left: 'yse', right: 'yes' }
const a1: 有左手的人 = b // 不报错

const a2: 有左手的人 = { left: 'yse', right: 'yes' } // 报错

可用于接口求交集

ts
interface Colorful {
  color: string;
}
interface Circle {
  radius: number;
}
type ColorfulCircle = Colorful & Circle;

可用于模拟继承

ts
type Person = {
  name: string;
  age: number;
};
type User = Person & {
  id: number;
  email: string;
};
const u: User = {
  id: 1,
  name: 'ClariS',
  age: 18,
  email: 'xxx@yyy.com'
};

交叉类型的特殊情况

ts
type Person = {
  name: string;
  age: number;
  id: string;
};
type User = Person & {
  id: number;
  email: string;
};
const u: User = {
  id: 1 as never, // 此处 id 的类型为 never
  name: 'ClariS',
  age: 18,
  email: 'xxx@yyy.com',
};

当把上面 id 的类型从一个比较大的类型,变为比较小的类型时,整个 User 的类型都为 never

ts
type Person = {
  name: string;
  age: number;
  id: 'A';
};
type User = Person & {
  id: 'B';
  email: string;
};
const u: User = { // User = never
  id: 1,
  name: 'ClariS',
  age: 18,
  email: 'xxx@yyy.com',
};

type A = { kind: 'A'; name: string };
type B = { kind: 'B'; age: number } & A;
//   ^-- never

上面的例子中,当对象属性发生冲突时,type 只会把类型变为 never,但类型并不报错,只在使用时报错;而 interface 会直接报错

ts
interface Person {
  name: string;
  age: number;
  id: string;
}
interface User extends Person {
  //        ^-- Type 'number' is not assignable to type 'string'
  id: number;
  email: string;
}

函数的交集会得到一个参数的并集

ts
type A = {
  method: (a: number) => void;
};
type B = {
  method: (a: string) => void;
} & A;

const b: B = {
  method(a) {
    a; // number | string
  }
};

总结:交叉类型常用于有交集的类型 A、B,如果 A、B 无交集,可能得到 never,也可能只是属性为 never

类型兼容与赋值
TS 中的类型运算:联合类型

评论区

评论加载中...