返回

TypeScript 进阶用法:联合类型与交叉类型,让类型系统更灵活

前端

  1. 联合类型:多种类型合而为一

联合类型,顾名思义,就是将多个类型合并为一个类型。就像 JavaScript 中的 || 操作符一样,TypeScript 中的联合类型使用 | 符号连接多个类型。例如:

let value: number | string;
value = 10; // 可以赋值为数字
value = "Hello"; // 也可以赋值为字符串

联合类型的声明和使用十分简单,但它却能为代码带来很大的灵活性。让我们看一个实际的例子:

function greet(name: string | null) {
  if (name) {
    console.log(`Hello, ${name}!`);
  } else {
    console.log("Hello, stranger!");
  }
}

在这个 greet 函数中,我们声明了一个 name 参数,它的类型是 string | null。这意味着 name 参数可以是字符串类型,也可以是 null 类型。

当我们调用 greet 函数时,我们可以传入字符串或 null 值:

greet("Alice"); // 输出:Hello, Alice!
greet(null); // 输出:Hello, stranger!

联合类型还可以把接口类型联合起来,表示更复杂的类型结构。例如:

interface User {
  name: string;
  age: number;
}

interface Admin extends User {
  permissions: string[];
}

type UserOrAdmin = User | Admin;

function promoteUser(user: UserOrAdmin) {
  if ("permissions" in user) {
    // 是管理员
    console.log(`Promoting admin ${user.name}...`);
  } else {
    // 是普通用户
    console.log(`Promoting user ${user.name}...`);
  }
}

在这个例子中,我们定义了一个 User 接口,一个 Admin 接口,然后将它们联合起来形成 UserOrAdmin 类型。这样,我们可以在一个函数中同时处理用户和管理员,而无需单独编写两个函数。

2. 交叉类型:多种类型合二为一

交叉类型与联合类型相反,它将多个类型合并为一个新的类型,这个新类型同时具有所有组成类型的特征。交叉类型使用 & 符号连接多个类型。例如:

type UserWithPermissions = User & { permissions: string[] };

function promoteUserWithPermissions(user: UserWithPermissions) {
  console.log(`Promoting user ${user.name} with permissions ${user.permissions}...`);
}

在这个例子中,我们定义了一个 UserWithPermissions 类型,它将 User 接口和一个包含 permissions 属性的对象类型组合在一起。这样,我们可以创建一个同时具有用户名、年龄和权限属性的对象。

3. 灵活运用联合类型和交叉类型

联合类型和交叉类型是 TypeScript 中非常强大的工具,它们可以帮助我们表示更复杂的类型结构,并编写出更健壮、更灵活的代码。

以下是使用联合类型和交叉类型的几个技巧:

  • 使用联合类型来表示可接受多种不同类型参数的函数。
  • 使用交叉类型来表示具有多个不同属性的对象类型。
  • 使用联合类型或交叉类型来创建更灵活的接口,以便它们可以被更多不同的类或对象实现。
  • 使用联合类型或交叉类型来创建更通用的泛型类型,以便它们可以被更多不同的数据类型使用。

掌握了联合类型和交叉类型,你将能够编写出更加灵活和强大的 TypeScript 代码。