TypeScript 联合类型与交叉类型深度解析

TypeScript 联合类型与交叉类型深度解析

TypeScript TypeScript 使用手册(中文版)翻译。http://www.typescriptlang.org TypeScript 项目地址: https://gitcode.com/gh_mirrors/typ/TypeScript

引言

在 TypeScript 类型系统中,联合类型(Union Types)和交叉类型(Intersection Types)是两种强大的类型组合工具。它们允许开发者基于现有类型创建新的类型组合,极大地增强了类型系统的表达能力。本文将深入探讨这两种类型的特性、使用场景和最佳实践。

联合类型:灵活的类型选择

基本概念

联合类型使用 | 操作符将多个类型组合在一起,表示一个值可以是其中任意一种类型。语法形式为 Type1 | Type2 | ... | TypeN

function padLeft(value: string, padding: string | number) {
  // ...
}

类型守卫与类型收窄

当处理联合类型时,TypeScript 会要求我们使用类型守卫来缩小类型范围:

function processValue(value: string | number) {
  if (typeof value === "string") {
    // 这里 value 被收窄为 string 类型
    return value.toUpperCase();
  } else {
    // 这里 value 被收窄为 number 类型
    return value.toFixed(2);
  }
}

可区分联合(标签联合)

这是一种高级模式,通过共享的字面量类型字段来区分联合中的不同类型:

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "square"; sideLength: number };

function getArea(shape: Shape) {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.sideLength ** 2;
  }
}

穷尽性检查

TypeScript 可以通过 never 类型帮助我们确保处理了联合类型的所有可能情况:

function assertNever(x: never): never {
  throw new Error("Unexpected value: " + x);
}

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle":
      return Math.PI * shape.radius ** 2;
    case "square":
      return shape.sideLength ** 2;
    default:
      return assertNever(shape); // 如果有未处理的类型会报错
  }
}

交叉类型:类型的组合

基本概念

交叉类型使用 & 操作符将多个类型合并为一个类型,新类型包含所有原类型的特性。语法形式为 Type1 & Type2 & ... & TypeN

interface Person {
  name: string;
}

interface Employee {
  id: number;
}

type Staff = Person & Employee;

const staff: Staff = {
  name: "Alice",
  id: 123
};

实际应用场景

  1. 混入(Mixins)模式:组合多个类的功能
  2. 扩展现有类型:添加额外属性而不修改原类型
  3. 组合多个接口:创建更复杂的类型
function extend<T, U>(first: T, second: U): T & U {
  const result = {};
  for (const prop in first) {
    (result as any)[prop] = first[prop];
  }
  for (const prop in second) {
    (result as any)[prop] = second[prop];
  }
  return result as T & U;
}

与联合类型的区别

| 特性 | 联合类型 | 交叉类型 | |--------------|-------------------------|-------------------------| | 操作符 | | | & | | 语义 | 类型之一 | 所有类型的组合 | | 属性访问 | 只能访问共有成员 | 可以访问所有成员 | | 常见用途 | 处理多种可能的输入 | 组合多个类型的特性 |

高级技巧与最佳实践

  1. 类型别名与联合/交叉类型结合:提高代码可读性
type Primitive = string | number | boolean;
type Nullable<T> = T | null | undefined;
  1. 条件类型中的联合与交叉:创建更灵活的类型工具
type NonNullable<T> = T extends null | undefined ? never : T;
  1. 避免过度使用交叉类型:复杂的交叉类型可能导致类型推断困难

  2. 优先使用接口扩展而非交叉:对于对象类型,interface extends 通常比 & 更清晰

常见问题解答

Q: 联合类型和交叉类型可以混合使用吗?

A: 可以,例如 (A | B) & (C | D) 表示类型必须满足 (A 或 B)(C 或 D) 的条件。

Q: 如何处理联合类型的数组?

A: 使用括号明确优先级,如 (Type1 | Type2)[] 表示数组元素可以是 Type1 或 Type2。

Q: 交叉类型与继承有何区别?

A: 交叉类型是静态组合,不会创建子类型关系;继承则创建了明确的层次结构。

总结

联合类型和交叉类型是 TypeScript 类型系统中非常重要的工具。联合类型提供了灵活性,允许一个值属于多种类型之一;而交叉类型则允许我们组合多个类型的特性。掌握这两种类型的使用,能够显著提升 TypeScript 代码的类型安全性和表达力。在实际开发中,应根据具体场景选择最合适的类型组合方式,并遵循类型设计的最佳实践。

TypeScript TypeScript 使用手册(中文版)翻译。http://www.typescriptlang.org TypeScript 项目地址: https://gitcode.com/gh_mirrors/typ/TypeScript

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

任澄翊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值