TypeScript 联合类型

TypeScript 中的联合类型(Union Types)详解

联合类型 是 TypeScript 类型系统中最强大的特性之一,使用 |(竖线)将多个类型组合起来,表示一个值可以是几种类型中的任意一种

1. 基本语法与用法

let id: string | number = 123;   // 可以是 string 或 number
id = "abc123";                   // OK
// id = true;                    // 错误:boolean 不属于联合类型

常见基础联合类型:

let flag: boolean | null = true;
flag = null;                     // OK

let status: "loading" | "success" | "error" = "loading";
status = "success";              // OK
// status = "failed";            // 错误:不是这三个值之一

2. 类型缩小(Type Narrowing)—— 联合类型的核心优势

TypeScript 会根据条件判断自动缩小变量的类型范围,提供更精确的类型检查和智能提示。

function printId(id: string | number) {
  // 这里 id 是 string | number

  if (typeof id === "string") {
    // TS 自动缩小:这里 id 是 string
    console.log(id.toUpperCase());  // 安全调用字符串方法
    console.log(id.length);
  } else {
    // TS 自动缩小:这里 id 是 number
    console.log(id.toFixed(2));     // 安全调用数字方法
  }
}

printId(123);      // 调用数字分支
printId("hello");  // 调用字符串分支

其他常见类型守卫(Type Guards)方式:

function process(value: string | null | number) {
  if (value === null) {
    // value 被缩小为 null
    return;
  }

  if (typeof value === "string") {
    // value 被缩小为 string
    value.toLowerCase();
  } else {
    // value 被缩小为 number
    value.toPrecision(2);
  }
}
  • typeof 检查原始类型(string/number/boolean/symbol/function)
  • === / !== 检查字面量或 null/undefined
  • 自定义类型守卫函数:
function isString(value: any): value is string {
  return typeof value === "string";
}

function log(value: string | number) {
  if (isString(value)) {
    // value 被缩小为 string
    console.log(value.repeat(2));
  }
}

3. 与其他类型的组合

a. 联合类型 + 数组
let mixedArray: (string | number)[] = [1, "two", 3, "four"];
mixedArray.push(5);      // OK
mixedArray.push("six");  // OK
// mixedArray.push(true); // 错误
b. 联合类型 + 对象属性
interface Success {
  type: "success";
  data: string;
}

interface Error {
  type: "error";
  message: string;
}

type Result = Success | Error;  // 可辨识联合(Discriminated Union)

function handleResult(result: Result) {
  if (result.type === "success") {
    // result 被缩小为 Success
    console.log(result.data.toUpperCase());
  } else {
    // result 被缩小为 Error
    console.log("错误:" + result.message);
  }
}

可辨识联合 是联合类型的最佳实践模式:通过一个共同的字面量属性(tag,如 typekind)来区分不同分支。

4. 联合类型与函数

// 参数为联合类型
function format(value: string | number): string {
  return typeof value === "number" ? value.toFixed(2) : value.trim();
}

// 返回值为联合类型
function getStatus(): "ok" | "failed" | null {
  return Math.random() > 0.5 ? "ok" : "failed";
}

5. 常见内置联合类型

  • string | null | undefined:常用于可选值(开启 strictNullChecks 时)
  • HTMLElement | null:如 document.getElementById()
  • any 可以看作是所有类型的联合(但不推荐使用)

6. 注意事项

  • 联合类型的方法限制:只能调用所有类型共有的方法。
let value: string | number = "hello";

// value.toUpperCase();  // 错误:number 上没有这个方法
value.toString();       // OK:string 和 number 都有 toString()
  • 使用类型守卫 来安全访问特定类型的方法。

7. 最佳实践建议

场景推荐用法
可能为空的值string | null | undefined + ???.
状态机"idle" | "loading" | "success" | "error"
API 响应可辨识联合(带 typekind 字段)
多类型参数联合类型 + 类型守卫函数
避免过度宽松尽量用具体字面量联合,而不是 string | number

小结:联合类型速查

写法含义示例场景
string | numberID 可以是字符串或数字用户ID、订单号
"left" | "right" | "center"固定字符串选项对齐方式、方向
Success | Error可辨识联合API 响应处理
T | null | undefined可空类型DOM 元素、配置值

联合类型是 TypeScript 类型安全的核心,配合类型缩小可辨识联合,能大幅减少运行时错误,提升代码可维护性。

如果您想深入了解交叉类型(Intersection Types)联合类型与泛型的结合、或条件类型(Conditional Types),请告诉我!

文章已创建 3383

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部