联合类型(Union Types)
联合类型表示一个值可以是几种类型之一。 我们用竖线( |)分隔每个类型,所以 number | string | boolean 表示一个值可以是 number, string,或 boolean。
正如联合类型的符号是|
,它代表了按位或,即只需要符合联合类型中的一个类型,既可以认为实现了这个联合类型,如A | B
,只需要实现 A 或 B 即可。 语法: Type1 | Type2 | ... | TypeN
Union Types 常用于函数参数或返回值的类型定义。
typescript
type Width = number | string;
let width: Width = 100; // 正确
width = "100px"; // 正确
function getLength(arg: number | string) {
// 在函数内部需要使用类型守卫来缩小类型
if (typeof arg === "number") {
return arg.toString().length;
} else {
return arg.length;
}
}
交叉类型(Intersection Types)
交叉类型使用 & 运算符,表示将多个类型合并为一个类型。新的类型将具有所有类型的特性。
语法: Type1 & Type2 & ... & TypeN
代表着按位与的 & 表示需要符合这里的所有类型,才可以说实现了这个交叉类型,即 A & B,需要同时满足 A 与 B 两个类型;交叉类型常用于组合现有的对象类型,从而创建新的对象类型。
typescript
interface Colorful {
color: string;
}
interface Circle {
radius: number;
}
type ColorfulCircle = Colorful & Circle;
let cc: ColorfulCircle = {
color: "red",
radius: 42,
};
typescript
type PartialPointX = { x: number };
type Point = PartialPointX & { y: number };
let point: Point = {
x: 1,
y: 1,
};
基本用法
typescript
interface NameStruct {
name: string;
}
interface AgeStruct {
age: number;
}
type ProfileStruct = NameStruct & AgeStruct;
const profile: ProfileStruct = {
name: "yyds",
age: 18,
};
ProfileStruct 其实就是一个新的,同时包含 NameStruct 和 AgeStruct 两个接口所有属性的类型。
对于原生类型:
typescript
type StrAndNum = string & number; // never
新的类型会同时符合交叉类型的所有成员,存在既是 string 又是 number 的类型吗?当然不。实际上,这也是 never 这一 BottomType 的实际意义之一,描述根本不存在的类型嘛。
同名基础类型属性合并
typescript
interface X {
c: string;
d: string;
}
interface Y {
c: number;
e: string;
}
type XY = X & Y;
type YX = Y & X;
let p: XY;
let q: YX;
p = { c: 6, d: "d", e: "e" }; // Error
q = { c: "c", d: "d", e: "e" }; // Error
// interface中有同名属性c ; &表示合并
// 表示c既可以是string 又是 number,明显这种类型不存在,所以c最后类型是never了
同名对象类型属性合并
对于对象类型的交叉类型,其内部的同名属性类型同样会按照交叉类型进行合并:
typescript
interface D {
d: boolean;
}
interface E {
e: string;
}
interface F {
f: number;
}
interface A {
x: D;
}
interface B {
x: E;
}
interface C {
x: F;
}
// 同名的x属性是一个非基本数据类型,可以成功合并
type ABC = A & B & C;
let abc: ABC = {
x: {
d: true,
e: "semlinker",
f: 666,
},
};
console.log("abc:", abc);
other eg. 两个联合类型组成的交叉类型, => 两边联合类型的交集:
typescript
type UnionIntersection1 = (1 | 2 | 3) & (1 | 2); // 1 | 2
type UnionIntersection2 = (string | number | symbol) & string; // string
总结一下交叉类型和联合类型的区别就是,联合类型只需要符合成员之一即可(||),而交叉类型需要严格符合每一位成员(&&)。