TypeScript 中等待的类型是什么

问题描述 投票:0回答:2

在最新版本的 TypeScript 4.5 中,有一个名为 Awaited 的新类型。看起来这种类型是用于处理承诺的。我发现文档中没有很好地描述这一点,并且我在任何地方都没有找到任何更好的示例。

有人可以解释一下这种类型的用途及其工作原理吗?

提前谢谢您。

typescript types
2个回答
26
投票

如果您正在寻找

Awaited<T>
实用程序类型的更详细和解释性文档,您可能需要查看TypeScript 4.5发行说明的相关部分以及实施拉取请求microsoft/TypeScript#45350 .

Awaited<T>
的目标是描述(也许令人惊讶的)在
await
函数中由
async
表示的复杂类型操作。 当您
await
某种类型
T
的值时,您将获得
Awaited<T>
类型的值:

async function foo<T>(x: T) {
    const y = await x;
    // const y: Awaited<T> in TS4.5 and above 
    // (just T in TS4.4 and below)
}

如果您正在

T
的类型
await
不是任何类型的
Promise
,则
Awaited<T>
T
相同:

async function bar(x: string) {
    const y = await x;
    // const y: string
    // Awaited<string> is just string
}

如果您正在

T
的类型
await
Promise<U>
,其中
U
不是任何类型的
Promise
,则
Awaited<T>
U
相同:

async function baz(x: Promise<string>) {
    const y = await x;
    // const y: string
    // Awaited<Promise<string>> is just string
}

当您的

T
类型是
await
时,事情会变得更加复杂;如果
Promise<Promise<V>>
不是
V
,则
Promise
Awaited<T>
相同:
V

那是因为 
async function qux(x: Promise<Promise<string>>) { const y = await x; // const y: string }

递归地解开
任何 await,直到它遇到非
Promise
(或一些可怕的错误情况,例如具有
Promise
方法的非 Promise 对象);你永远不应该从
then()
中得到
Promise
:
await

所以这意味着
async function quux(x: Promise<Promise<Promise<Promise<string>>>>) { const y = await x; // const y: string }

也通过以下

递归条件类型
递归地解开promise: Awaited<T>

它还处理
联合类型

;例如,如果您有 either a /** * Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to `never`. This emulates the behavior of `await`. */ type Awaited<T> = T extends null | undefined ? T : // special case for `null | undefined` // when not in `--strictNullChecks` mode T extends object & { then(onfulfilled: infer F, ...args: infer _): any } ? // `await` only unwraps object types with a callable `then`. // Non-object types are not unwrapped F extends ((value: infer V, ...args: infer _) => any) ? // if the argument to `then` is callable, extracts the first argument Awaited<V> : // recursively unwrap the value never : // the argument to `then` was not callable T; // non-object or non-thenable

or
a string
Promise<number>
,那么您将得到
either
a await
a string
number

等等递归包装的联合:

async function union(x: string | Promise<number>) { const y = await x; // const y: string | number }

在 TypeScript 4.5 之前,上述 
async function wha(x: number | Promise<string | Promise<number | Promise<Promise<boolean>>>>) { const y = await x; // const y: string | number | boolean }

大部分都有效,但存在一些故障,特别是围绕

await
组合方法的行为,如
Promise
:
Promise.all()

因此,引入 
async function oops(x1: Promise<string | Promise<number>>, x2: Promise<string | Promise<number>>) { const y = await Promise.all([x1, x2]); // const y: [string | Promise<number>, string | Promise<number>] in TS4.4 and below 😭 // const y: [string | number, string | number] in TS4.5 and above 😊 }

类型是为了更全面地处理

Awaited<T>
操作的影响,面对人们报告为错误的一些奇怪的边缘情况(您可以在 microsoft/TypeScript#45350 中看到)。
在实践中,您可能不需要自己处理太多问题,但它的存在很有帮助。

Playground 代码链接


18
投票
Promise

,你将得到:

Awaited<X>

所以:

X - If X was not a promise, Y - If X was Promise<Y> Z - If X had the type Promise<Promise<Z>>

这个想法是,在 Javascript 中,你可以等待非承诺并返回相同的值:

Awaited<number> -> Gives you number Awaited<Promise<string>> -> Gives you string Awaited<Promise<Promise<boolean>>> -> Gives you boolean

在引入 
const x = await 5; // x = 5

之前,上面的例子已经有些可能了,但是当 Promise 类型像

Awaited
那样嵌套时,它会变得很奇怪,所以 tl;dr 是:

Promise<Promise<Y>>

类型是当您

Awaited<X>
类型为
await
的东西时得到的。换句话说,它会删除任意数量的
X
包装器。 (或者更具体地说,
Promise
)。
    

© www.soinside.com 2019 - 2024. All rights reserved.