联合类型

联合类型表示一个值可以是多种类型之一。使用 | 符号连接多个类型,让类型定义更加灵活。

基本语法

联合类型使用 | 符号连接多个类型。

type StringOrNumber = string | number

let value: StringOrNumber

value = "hello"
console.log(value)

value = 123
console.log(value)

value 变量可以是字符串或数字。

联合类型与函数

联合类型常用于函数参数,允许接受多种类型的参数。

function format(value: string | number): string {
  if (typeof value === "string") {
    return value.toUpperCase()
  }
  return value.toFixed(2)
}

console.log(format("hello"))
console.log(format(3.14159))

函数内部需要使用类型守卫区分具体类型。

联合类型与数组

联合类型可以用于数组元素。

type MixedArray = (string | number)[]

const arr: MixedArray = [1, "two", 3, "four"]

arr.forEach(item => {
  if (typeof item === "string") {
    console.log(`字符串: ${item}`)
  } else {
    console.log(`数字: ${item}`)
  }
})

数组元素可以是字符串或数字。

字面量联合类型

联合类型可以与字面量类型结合,限制具体的值。

type Direction = "up" | "down" | "left" | "right"

function move(direction: Direction): void {
  console.log(`向 ${direction} 移动`)
}

move("up")
move("down")

Direction 只能是四个字符串值之一,提供更严格的类型检查。

对象联合类型

联合类型可以用于对象。

interface Bird {
  type: "bird"
  flyingSpeed: number
}

interface Horse {
  type: "horse"
  runningSpeed: number
}

type Animal = Bird | Horse

function getSpeed(animal: Animal): number {
  switch (animal.type) {
    case "bird":
      return animal.flyingSpeed
    case "horse":
      return animal.runningSpeed
  }
}

const bird: Bird = { type: "bird", flyingSpeed: 100 }
const horse: Horse = { type: "horse", runningSpeed: 80 }

console.log(getSpeed(bird))
console.log(getSpeed(horse))

使用可辨识属性 type 区分不同的对象类型。

类型缩小

联合类型需要类型缩小才能访问特定类型的属性。

interface Fish {
  swim: () => void
}

interface Bird {
  fly: () => void
}

type Pet = Fish | Bird

function move(pet: Pet) {
  if ("swim" in pet) {
    pet.swim()
  } else {
    pet.fly()
  }
}

in 操作符检查对象是否有某个属性,帮助缩小类型范围。

联合类型与 null

联合类型常用于处理可能为 null 或 undefined 的值。

type MaybeString = string | null | undefined

function process(value: MaybeString): string {
  if (value == null) {
    return "空值"
  }
  return value.toUpperCase()
}

console.log(process("hello"))
console.log(process(null))
console.log(process(undefined))

MaybeString 可以是字符串、null 或 undefined。

联合类型的限制

联合类型只能访问所有类型共有的成员。

interface Circle {
  radius: number
}

interface Rectangle {
  width: number
  height: number
}

type Shape = Circle | Rectangle

function getArea(shape: Shape): number {
  if ("radius" in shape) {
    return Math.PI * shape.radius * shape.radius
  }
  return shape.width * shape.height
}

直接访问 radiuswidth 会报错,需要先进行类型缩小。

实际应用

联合类型在实际开发中常用于处理多种可能的数据格式。

type Result = Success | Failure

interface Success {
  status: "success"
  data: {
    id: number
    name: string
  }
}

interface Failure {
  status: "failure"
  error: string
}

function handleResult(result: Result) {
  switch (result.status) {
    case "success":
      console.log(`成功: ${result.data.name}`)
      break
    case "failure":
      console.log(`失败: ${result.error}`)
      break
  }
}

handleResult({
  status: "success",
  data: { id: 1, name: "张三" }
})

handleResult({
  status: "failure",
  error: "网络错误"
})

Result 类型表示操作可能成功或失败,使用可辨识联合处理不同情况。

小结

联合类型使用 | 符号连接多个类型,表示值可以是其中任意一种。联合类型常用于函数参数、数组元素和对象类型。字面量联合类型可以限制具体的值。使用联合类型时需要类型缩小才能访问特定类型的属性。联合类型是处理多种可能值的重要工具。