在TypeScript中,联合类型(Union Types)和交叉类型(Intersection Types)是两种用于表示复杂数据结构的强大工具。下面将详细解释如何在实际场景中使用它们。
联合类型(Union Types)
联合类型允许你将多个类型组合成一个类型,这个类型可以是组合中任意一个类型的值。
使用场景:
- 当一个变量可以是多种类型之一时。
- 函数可以返回多种类型之一时。
示例:
// 定义一个联合类型
let myVar: string | number | boolean;
// 赋值
myVar = "Hello"; // 正确
myVar = 42; // 正确
myVar = true; // 正确
// 访问属性或方法时,需要类型守卫或类型断言
if (typeof myVar === "string") {
console.log(myVar.toUpperCase()); // 类型守卫
}
// 或者使用类型断言
console.log((myVar as string).toUpperCase()); // 注意:如果myVar不是string,这里会运行时错误
// 函数返回联合类型
function getData(): string | number {
return Math.random() > 0.5 ? "string" : 123;
}
let data = getData();
if (typeof data === "string") {
console.log(data.length);
} else {
console.log(data * 2);
}
交叉类型(Intersection Types)
交叉类型将多个类型合并为一个类型,这个新类型具有所有类型的特性。
使用场景:
- 当你想扩展一个类型,但又不想使用继承时。
- 当你需要一个对象同时满足多个接口时。
示例:
interface IPerson {
name: string;
age: number;
}
interface IEmployee {
id: number;
role: string;
}
// 交叉类型
type Employee = IPerson & IEmployee;
// 创建一个Employee类型的对象
let employee: Employee = {
name: "John Doe",
age: 30,
id: 1,
role: "Developer"
};
console.log(employee.name); // John Doe
console.log(employee.role); // Developer
// 创建一个函数,该函数接收Employee类型的参数
function greetEmployee(emp: Employee) {
console.log(`Hello, ${emp.name}. Your role is ${emp.role}.`);
}
greetEmployee(employee); // Hello, John Doe. Your role is Developer.
注意事项
- 当使用联合类型时,如果你尝试访问一个可能不存在的属性或方法,TypeScript编译器会报错。这时,你可以使用类型守卫(如
typeof
、instanceof
等)或类型断言来告诉编译器你确切知道这个变量当前是什么类型。 - 交叉类型非常强大,但也要避免创建过于复杂的类型结构,这可能会使代码难以理解和维护。
- 在使用交叉类型时,如果两个类型有相同的属性名但类型不同,那么这些属性在交叉类型中的类型将是这两个类型的交集(如果它们有交集的话),否则会导致编译错误。但在实践中,这种情况比较少见,因为通常我们会避免给不同的接口或类型定义相同的属性名。