当前位置: 首页 > 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.jsqmd.com/news/937677/

相关文章:

  • 2026年赤峰劳动工伤律师推荐:5位实战经验丰富值得信赖的维权专家 - 本地品牌推荐
  • 2026年济南黄金回收实用科普:素军奢品汇贵金属回收闲置处置参考文稿 - GrowthUME
  • 【AI笔记】环境配置
  • 如何通过OmenSuperHub优化惠普OMEN游戏本的性能和散热
  • 2026 HENGSHI BOX 全域智控舱技术白皮书:衡石科技软硬一体的私有化 Agentic BI 架构
  • 7次碰壁、4个版本:我在一个浏览器插件里看到Agent该有的样子
  • 铜箔胶带电路制作:LED发光蝙蝠的串联电路实践
  • 告别零碎作业:留学生如何把大学四年代码重构为可交付全栈「蒸汽求职分享」
  • 【Agent 学习日记】我们来说说 Agent 记忆压缩通常有哪些方法?
  • 2026 短视频去水印软件推荐,抖音快手视频号通用 - 时时资讯
  • 10.使用requests库爬取网易云音乐
  • 国内飞往澳大利亚全航线汇总|特价经济 / 特惠公务 / 折扣商务头等舱申请|靠谱国际机票代理人优选:武汉圣擎航空(15120088536 微信同号) - 土星买买买
  • 从零打造2000W正弦波逆变器:PIC单片机控制与全桥功率设计实战
  • Buck 滑模变结构控制(SMC)仿真
  • 3.4 Linux目录操作
  • 高级实时数据编辑方案:COM3D2.MaidFiddler架构深度解析
  • Axure9.0中继器-初识篇
  • 全球特价机票深度指南:从武汉圣擎航空服务看南非、法国航线如何买到最划算的公务舱与紧急售后保障 - 土星买买买
  • 从干涉仪到人眼像差:一文读懂Zernike多项式在不同光学场景下的“变脸”艺术
  • 西安卖黄金别再被扣损耗,2026金条变现拒绝压价套路避雷指南TOP10 - 西安闲转记
  • 从 Defense 到大学科研经费,再到政府预算,SAP Public Services 的业务底座到底在管什么
  • Unlock-Music终极指南:3分钟解锁所有加密音乐文件的完整教程
  • 北京五恒系统厂家推荐:北京五恒系统怎么选?厂家、品牌、口碑、价格一篇看懂 - GrowthUME
  • mootdx通达信数据接口:Python量化金融数据获取的现代化解决方案
  • C++:红黑树实现
  • Outfit字体:9种字重几何无衬线字体的完整免费解决方案
  • yuzu模拟器流畅运行终极方案:告别卡顿闪退的7个关键技巧
  • 从博弈论到你的Jupyter Notebook:手把手拆解SHAP值计算原理与实战调优
  • 洛雪音乐音源完全指南:5分钟打造你的专属高品质音乐库
  • Android: 事件分发