TypeScript中Promise.all()字面量类型推断异常原因与解决方法
TypeScript Promise.all字面量类型匹配异常解析
复现代码
(async () => { const [a]: ['test'] = await Promise.all([Promise.resolve('test')]) // ^ 此处提示类型不匹配:string类型不能赋值给'test'类型 const b: 'test' = await Promise.resolve('test') console.log(a, b) })()
底层推断逻辑与异常原因
两个场景的推断差异完全来自TS的类型拓宽规则和泛型重载匹配逻辑:
- 直接调用
Promise.resolve('test')时,泛型参数会根据传入的字符串字面量直接窄化推断为'test',await解包Promise后得到的值类型就是'test',和标注类型匹配,不会报错。 - 调用
Promise.all([Promise.resolve('test')])时,TS会默认把方括号包裹的数组字面量推断为普通数组类型Promise<string>[],而非固定长度、固定位置类型的元组类型[Promise<'test'>]——这是TS的默认设计:可变数组默认做类型拓宽,方便后续调用push、pop等数组方法。 - 对照TS内置的
Promise.all类型重载:当入参是普通数组Promise<T>[]时,返回值解包后为T[];只有入参是元组类型时,才会按位置解包每个Promise的类型返回对应元组。因此入参被推断为Promise<string>[]时,await后的返回值是string[],解构出的a类型为string,自然无法赋值给字面量类型'test',触发类型错误。
解决方案
三种方案都可以绕过默认的数组类型拓宽,让TS正确识别元组类型:
- 给传入
Promise.all的数组添加as const断言,将其标记为只读元组,阻止类型拓宽(async () => { const [a]: ['test'] = await Promise.all([Promise.resolve('test')] as const) const b: 'test' = await Promise.resolve('test') console.log(a, b) })() - 显式为
Promise.all指定泛型参数,直接声明返回的元组类型,跳过入参的默认拓宽推断(async () => { const [a]: ['test'] = await Promise.all<['test']>([Promise.resolve('test')]) const b: 'test' = await Promise.resolve('test') console.log(a, b) })() - 提前定义传入的Promise数组为元组类型,从源头避免被推断为普通数组
(async () => { const promiseList: [Promise<'test'>] = [Promise.resolve('test')] const [a]: ['test'] = await Promise.all(promiseList) const b: 'test' = await Promise.resolve('test') console.log(a, b) })()
内容的提问来源于stack exchange,提问作者Fox Amadeus
相关产品推荐
相关产品推荐

