TypeScript 中的可辨识联合(Discriminated Unions)设计模式

 更新时间:2026年05月27日 10:08:52   作者:csdddn  
TypeScript的可辨识联合(Discriminated Unions)是一种结合联合类型和字面量类型的设计模式,用于安全处理多种数据类型,本文就来详细的介绍一下TypeScript可辨识联合的使用,感兴趣的可以了解一下

引言

在 TypeScript 开发中,处理多种可能的数据类型是常见需求。可辨识联合(Discriminated Unions)设计模式提供了一种强大且类型安全的方式来处理这类场景。它通过结合联合类型和字面量类型,使得开发者能够清晰地表达不同数据类型之间的差异,并在编译时获得准确的类型检查。

可辨识联合的基本概念

可辨识联合由两部分组成:可辨识属性和联合类型。可辨识属性是一个具有明确字面量类型的属性,它作为区分不同类型成员的标志。联合类型则将多个具有共同可辨识属性的类型组合在一起。

例如,考虑一个表示不同形状的场景。我们可以定义一个具有 kind 可辨识属性的联合类型,其中 kind 的值用于区分不同的形状类型:

type Square = {
  kind: 'square';
  size: number;
};

type Rectangle = {
  kind: 'rectangle';
  width: number;
  height: number;
};

type Circle = {
  kind: 'circle';
  radius: number;
};

type Shape = Square | Rectangle | Circle;

在上述代码中,kind 是可辨识属性,Shape 是联合类型,它包含了 SquareRectangleCircle 三种不同的形状类型。

可辨识联合的类型推断

当使用可辨识联合时,TypeScript 能够根据可辨识属性的值进行精确的类型推断。这使得在处理联合类型的成员时,代码更加安全和可靠。

例如,我们可以编写一个函数来计算不同形状的面积:

function calculateArea(shape: Shape): number {
  switch (shape.kind) {
    case'square':
      return shape.size * shape.size;
    case'rectangle':
      return shape.width * shape.height;
    case 'circle':
      return Math.PI * shape.radius * shape.radius;
  }
}

calculateArea 函数中,switch 语句根据 shape.kind 的值进行分支判断。TypeScript 能够根据每个 case 语句中的值,推断出 shape 的具体类型,从而提供准确的类型提示和检查。例如,在 case'square' 分支中,shape 被推断为 Square 类型,我们可以安全地访问 size 属性。

可辨识联合的完整性检查

可辨识联合还提供了完整性检查的功能。当使用 switch 语句处理可辨识联合时,如果遗漏了某个可能的类型分支,TypeScript 会发出警告,提醒开发者处理所有可能的情况。

例如,如果我们忘记处理 Circle 类型的情况:

function calculateAreaIncomplete(shape: Shape): number {
  switch (shape.kind) {
    case'square':
      return shape.size * shape.size;
    case'rectangle':
      return shape.width * shape.height;
    // 缺少 case 'circle' 分支
  }
}

TypeScript 会提示 Function lacks ending return statement and return type does not include 'undefined',因为编译器检测到 switch 语句没有覆盖所有可能的 Shape 类型,可能导致函数在某些情况下没有返回值。

可辨识联合在实际项目中的应用

状态管理

在状态管理库中,可辨识联合常用于表示不同的状态类型。例如,在一个简单的计数器应用中,我们可以定义不同的状态类型:

type CounterState = {
  kind: 'initial';
} | {
  kind: 'incremented';
  count: number;
} | {
  kind: 'decremented';
  count: number;
};

function updateCounter(state: CounterState, action: 'increment' | 'decrement'): CounterState {
  switch (state.kind) {
    case 'initial':
      return action === 'increment'? { kind: 'incremented', count: 1 } : { kind: 'decremented', count: -1 };
    case 'incremented':
      return action === 'increment'? { kind: 'incremented', count: state.count + 1 } : { kind: 'decremented', count: state.count - 1 };
    case 'decremented':
      return action === 'increment'? { kind: 'incremented', count: state.count + 1 } : { kind: 'decremented', count: state.count - 1 };
  }
}

在这个例子中,CounterState 联合类型表示计数器的不同状态,updateCounter 函数根据当前状态和操作更新计数器的状态。

异步操作结果处理

在处理异步操作时,可辨识联合可以用于表示操作的成功或失败结果。例如:

type ApiResult<T> = {
  kind: 'success';
  data: T;
} | {
  kind: 'error';
  message: string;
};

async function fetchData(): Promise<ApiResult<string>> {
  try {
    const response = await fetch('https://example.com/api/data');
    const data = await response.text();
    return { kind:'success', data };
  } catch (error) {
    return { kind: 'error', message: error.message };
  }
}

async function processData() {
  const result = await fetchData();
  switch (result.kind) {
    case'success':
      console.log('Data:', result.data);
      break;
    case 'error':
      console.error('Error:', result.message);
      break;
  }
}

在这个例子中,ApiResult 联合类型表示异步操作的结果,fetchData 函数返回一个 Promise<ApiResult<string>>processData 函数根据操作结果进行不同的处理。

总结

可辨识联合是 TypeScript 中一种强大且实用的设计模式。它通过可辨识属性和联合类型的结合,提供了精确的类型推断和完整性检查,使得代码更加安全和可靠。在实际项目中,可辨识联合广泛应用于状态管理、异步操作结果处理等场景,帮助开发者更好地组织和管理复杂的数据类型。通过合理使用可辨识联合,开发者可以编写出更具可维护性和类型安全性的 TypeScript 代码。

到此这篇关于TypeScript 中的可辨识联合(Discriminated Unions)设计模式的文章就介绍到这了,更多相关TypeScript 可辨识联合内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • javascript parseInt() 函数的进制转换注意细节

    javascript parseInt() 函数的进制转换注意细节

    parseInt(string, radix) 有2个参数,第一个string 是传入的数值,第二个radix是 传入数值的进制,参数radix 可以忽略,默认为 10,各种进制的数转换为 十进制整数,接下来详细介绍,感兴趣的朋友可以了解下哦
    2013-01-01
  • javascript 用局部变量来代替全局变量

    javascript 用局部变量来代替全局变量

    在JavaScript中,我们应该尽可能的用局部变量来代替全局变量,这句话所有人都知道,可是这句话是谁先说的?
    2009-05-05
  • JS实现随机点名器

    JS实现随机点名器

    这篇文章主要为大家详细介绍了JS实现随机点名器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • js实现的下拉框二级联动效果

    js实现的下拉框二级联动效果

    这篇文章主要介绍了js实现的下拉框二级联动效果,涉及JavaScript针对页面元素的遍历与节点操作相关技巧,需要的朋友可以参考下
    2016-04-04
  • Array栈方法和队列方法的特点说明

    Array栈方法和队列方法的特点说明

    本篇文章主要是对Array栈方法与队列方法的特点进行了详细的说明介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2014-01-01
  • 浅析JavaScript中回调地狱与asyn函数和await函数原理

    浅析JavaScript中回调地狱与asyn函数和await函数原理

    这篇文章主要介绍了JavaScript中回调地狱与asyn函数和await函数原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-01-01
  • 理解javascript中try...catch...finally

    理解javascript中try...catch...finally

    这篇文章主要帮助大家理解javascript中try...catch...finally,从浅入深,一步步掌握javascript中try...catch...finally的使用方法,感兴趣的小伙伴们可以参考一下
    2015-12-12
  • 微信小程序wx.navigateTo方法里的events参数使用详情及场景

    微信小程序wx.navigateTo方法里的events参数使用详情及场景

    这篇文章主要介绍了微信小程序wx.navigateTo方法里的events参数使用详情及场景,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01
  • JS使用for in有序获取对象数据

    JS使用for in有序获取对象数据

    这篇文章主要介绍了JS使用for in有序获取对象数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • layui 监听弹窗关闭并刷新父级table的场景分析

    layui 监听弹窗关闭并刷新父级table的场景分析

    这篇文章主要介绍了layui 监听弹窗关闭并刷新父级table的场景分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-07-07

最新评论