TypeScript 交叉类型
介绍
在 TypeScript 中,交叉类型(Intersection Types) 是一种将多个类型合并为一个新类型的方式。通过交叉类型,我们可以组合多个类型的特性,从而创建出更复杂、更灵活的类型。交叉类型使用 &
符号来表示。
简单来说,交叉类型可以理解为“类型合并”。例如,如果你有两个类型 A
和 B
,那么 A & B
将同时具备 A
和 B
的所有属性。
基本语法
交叉类型的基本语法如下:
type CombinedType = TypeA & TypeB;
其中,TypeA
和 TypeB
是任意类型,CombinedType
是一个新类型,它包含了 TypeA
和 TypeB
的所有属性。
示例 1:合并对象类型
假设我们有两个对象类型 Person
和 Employee
:
type Person = {
name: string;
age: number;
};
type Employee = {
employeeId: number;
department: string;
};
type EmployeePerson = Person & Employee;
在这个例子中,EmployeePerson
类型将同时具备 Person
和 Employee
的所有属性。我们可以这样使用它:
const employee: EmployeePerson = {
name: "Alice",
age: 30,
employeeId: 12345,
department: "Engineering",
};
注意:交叉类型要求新类型的对象必须同时满足所有被合并类型的约束。如果缺少任何一个属性,TypeScript 会报错。
示例 2:合并函数类型
交叉类型不仅可以用于对象类型,还可以用于函数类型。例如:
type Greet = (name: string) => string;
type Log = (message: string) => void;
type GreetAndLog = Greet & Log;
在这个例子中,GreetAndLog
是一个同时具备 Greet
和 Log
特性的函数类型。
交叉类型的实际应用
场景 1:扩展现有类型
假设我们有一个基础的 User
类型,但我们希望在某些情况下扩展它,添加额外的属性。这时,交叉类型就派上用场了。
type User = {
id: number;
username: string;
};
type Admin = User & {
permissions: string[];
};
const admin: Admin = {
id: 1,
username: "admin",
permissions: ["read", "write", "delete"],
};
在这个例子中,Admin
类型扩展了 User
类型,添加了 permissions
属性。
场景 2:组合多个接口
在实际开发中,我们可能需要组合多个接口来创建一个新的类型。例如:
interface Serializable {
serialize(): string;
}
interface Loggable {
log(message: string): void;
}
type Logger = Serializable & Loggable;
class ConsoleLogger implements Logger {
serialize() {
return "Serialized data";
}
log(message: string) {
console.log(message);
}
}
在这个例子中,Logger
类型同时具备 Serializable
和 Loggable
的特性。
交叉类型与联合类型的区别
交叉类型(&
)和联合类型(|
)是 TypeScript 中两种不同的类型组合方式。
- 交叉类型:将多个类型合并为一个新类型,新类型具备所有类型的特性。
- 联合类型:表示一个值可以是多种类型中的一种。
例如:
type A = { a: number };
type B = { b: string };
type Intersection = A & B; // { a: number, b: string }
type Union = A | B; // 可以是 A 或 B 中的一种
总结
交叉类型是 TypeScript 中一种强大的工具,它允许我们通过组合多个类型来创建更复杂、更灵活的类型。无论是扩展现有类型,还是组合多个接口,交叉类型都能帮助我们更好地组织代码。
在实际开发中,交叉类型常用于以下场景:
- 扩展对象类型。
- 组合多个接口。
- 创建具备多种特性的函数类型。
附加资源与练习
练习 1
定义一个 Car
类型和一个 Engine
类型,然后使用交叉类型创建一个 CarWithEngine
类型。
练习 2
尝试将交叉类型与泛型结合使用,创建一个通用的 CombinedType<T, U>
类型。