当前位置: 首页 > news >正文

类型体操实战:Promise.all 类型实现

类型体操实战:Promise.all 类型实现

在 TypeScript 编程中,类型体操是一项重要的技能,它涉及对类型系统的深入理解和灵活运用。本文将聚焦于一个具体的类型体操实战案例:实现 Promise.all 的类型。

Promise.all 的基本功能

Promise.all 是 JavaScript 中一个常用的方法,它接收一个 Promise 对象的数组作为参数,并返回一个新的 Promise。这个新 Promise 的结果是一个数组,包含了每个输入 Promise 的结果。如果任何一个输入 Promise 被拒绝,返回的 Promise 也会立即被拒绝,并带有相同的拒绝原因。

类型挑战

在 TypeScript 中,我们需要为 Promise.all 实现一个类型,这个类型能够正确地推断出输入 Promise 数组中每个 Promise 的结果类型,并将它们组合成一个结果数组类型。这听起来似乎很简单,但实际上需要我们对 TypeScript 的类型系统有深入的理解。

初步尝试

首先,我们可能会尝试这样定义 Promise.all 的类型:

declarefunctionPromiseAll<T>(values:readonlyPromise<T>[]):Promise<T[]>;

然而,这种定义过于简单,它假设了数组中的所有 Promise 都具有相同的类型 T。但在实际应用中,Promise 数组中的元素可能具有不同的类型。因此,我们需要一种更灵活的方式来描述这种类型。

使用泛型和元组类型

为了处理 Promise 数组中元素类型可能不同的情况,我们可以使用泛型和元组类型。元组类型允许我们定义一个固定长度的数组,其中每个元素可以有不同的类型。我们可以利用这一点来推断 Promise.all 返回的 Promise 的结果类型。

下面是一个更接近正确实现的尝试:

declarefunctionPromiseAll<Textendsany[]>(values:readonly[...Promise<T>[]]):Promise<{[KinkeyofT]:Awaited<T[K]>}>;

在这个定义中,T extends any[]表示 T 是一个数组类型。readonly [...Promise<T>[]]是一个变长元组类型,它表示一个只读的、由 Promise 组成的元组,其中每个 Promise 的结果类型对应于 T 数组中的相应类型。

Awaited<T[K]>是一个内置的工具类型,用于获取 Promise 解析后的类型。{ [K in keyof T]: Awaited<T[K]> }是一个映射类型,它将 T 数组中的每个类型映射为其对应的 Awaited 类型,从而得到结果数组的类型。

完善实现

虽然上面的定义已经接近正确,但它仍然有一些问题。特别是,它没有正确地处理 Promise 数组为空的情况。为了完善实现,我们可以使用条件类型来检查 T 是否为空数组,并相应地调整返回类型。

下面是一个更完善的实现:

typeAwaited<T>=TextendsPromise<inferU>?U:T;typePromiseAllType<Textendsreadonlyany[]>=Textendsreadonly[]?Promise<[]>:Promise<{[KinkeyofT]:Awaited<Extract<T[K],Promise<any>>>extendsnever?T[K]:Awaited<Extract<T[K],Promise<any>>>;}>;declarefunctionPromiseAll<Textendsreadonlyany[]>(values:T):PromiseAllType<T>;

在这个实现中,我们首先定义了一个Awaited类型别名,用于获取 Promise 解析后的类型。然后,我们定义了一个PromiseAllType条件类型,它根据输入数组 T 是否为空来返回不同的类型。如果 T 是空数组,则返回Promise<[]>;否则,返回一个映射类型,将 T 中的每个元素映射为其对应的 Awaited 类型(如果它是 Promise 的话)。

Extract<T[K], Promise<any>>用于从 T[K] 中提取出 Promise 类型(如果存在的话)。如果 T[K] 不是 Promise 类型,则Extract的结果将是never,此时我们保留 T[K] 的原始类型。

使用示例

现在,我们可以使用这个实现来正确地推断 Promise.all 的返回类型了。例如:

constpromise1=Promise.resolve(1);constpromise2=Promise.resolve('hello');constpromise3=Promise.resolve(true);constresult=PromiseAll([promise1,promise2,promise3]);// result 的类型是 Promise<[number, string, boolean]>

在这个例子中,PromiseAll 能够正确地推断出输入 Promise 数组中每个 Promise 的结果类型,并将它们组合成一个结果数组类型。

总结

通过本文的实战案例,我们深入了解了 TypeScript 类型体操的魅力。通过使用泛型、元组类型、条件类型和映射类型等高级特性,我们能够实现对复杂类型关系的精确描述和推断。这不仅提高了代码的类型安全性,也增强了代码的可读性和可维护性。

http://www.rkmt.cn/news/1449031.html

相关文章:

  • 2026年济南黄金回收实用科普:素军奢品汇贵金属回收闲置处置参考文稿 - GrowthUME
  • 2026年赤峰劳动工伤律师推荐:5位实战经验丰富值得信赖的维权专家 - 本地品牌推荐
  • 如何通过OmenSuperHub优化惠普OMEN游戏本的性能和散热
  • 7次碰壁、4个版本:我在一个浏览器插件里看到Agent该有的样子
  • Axure9.0中继器-初识篇
  • 3.4 Linux目录操作
  • Buck 滑模变结构控制(SMC)仿真
  • Outfit字体:9种字重几何无衬线字体的完整免费解决方案
  • yuzu模拟器流畅运行终极方案:告别卡顿闪退的7个关键技巧
  • 告别网盘限速:LinkSwift 终极下载助手完全指南
  • 2026年6月国内热门的普拉提学校推荐,普拉提,普拉提机构哪家好 - 品牌推荐师
  • 解锁B站宝藏:用Python开源工具打造你的个人视频图书馆
  • Obsidian插件翻译终极指南:5分钟让任意插件说中文
  • 微信QQ消息防撤回实战指南:保护你的聊天记录不被消失
  • 微信聊天记录终极备份指南:永久保存你的数字记忆
  • 2026指纹浏览器字体指纹溯源机制:系统私有字体栈引发的隐性集群风控详解
  • 告别单调命令行:手把手教你用PS1变量打造高颜值Linux终端(附常用配色方案)
  • AI智能体领域术语乱象终结者!超全词汇表帮你秒懂Harness、Scaffold、Agent等核心概念!
  • 鸣潮模组终极指南:15+强力功能解锁,5分钟打造你的专属游戏体验
  • 终极指南:用Mem Reduct让Windows电脑告别卡顿,轻松管理内存
  • 在线浊度计十大品牌推荐:2026国产技术突围与精准选型指南 - 仪表品牌排行榜
  • 支持多账本的极简实用记账工具推荐
  • 2026年10款靠谱论文降AI率软件实测:降AI率实战对比实用指南 - 降AI小能手
  • 如何快速解决Windows更新问题:终极修复工具完整指南
  • ASP与jmail发送邮件:一次实用的回顾
  • 黑龙江省专升本资料|2026外语专业基础课真题精练
  • 洛雪音乐音源完全指南:打破音乐平台限制的终极解决方案
  • Arduino互动装置实战:超声波传感与伺服电机驱动恐怖画作
  • qoder-体验分享
  • 51单片机+DS18B20温度报警器保姆级教程:从Proteus仿真到普中开发板烧录全流程