在最新版本的 TypeScript 4.5 中,有一个名为 Awaited 的新类型。看起来这种类型是用于处理承诺的。我发现文档中没有很好地描述这一点,并且我在任何地方都没有找到任何更好的示例。
有人可以解释一下这种类型的用途及其工作原理吗?
提前谢谢您。
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
ora
string
和 Promise<number>
,那么您将得到 eithera
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 代码链接
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
)。