说我有以下代码:
async promiseOne() {
return 1
} // => Promise<number>
const promisedOne = promiseOne()
typeof promisedOne // => Promised<number>
我如何提取承诺结果的类型(在这个简化的情况下是一个数字)作为它自己的类型?
答案 0 :(得分:18)
从Typescript 2.8开始,现在可以通过利用条件类型来实现,这是一个基本的例子:
UnsatisfiableError: The following specifications were found to be in conflict:
- dlib
- xlwt
Use "conda info <package>" to see the dependencies for each package.
扩展function promiseOne() {
return Promise.resolve(1)
}
const promisedOne = promiseOne()
type ThenArg<T> = T extends Promise<infer U> ? U : T
type PromiseOneThenArg = ThenArg<typeof promisedOne> // => number
帮助程序以处理函数返回类型也可能很有用。
ThenArg
答案 1 :(得分:7)
首先,TypeScript 4.1 release notes具有以下代码段:
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
它可以让您解决诸如const x = (url: string) => fetch(url).then(x => x.json())
之类的问题,但是将Jon Jaques的回答与ErikE的评论相结合,并且考虑到您使用的版本低于4.1,我们得到:
type Await<T> = T extends PromiseLike<infer U> ? U : T
和示例:
const testPromise = async () => 42
type t1 = Await<ReturnType<typeof testPromise>>
// t1 => number
答案 2 :(得分:6)
如果您有权访问npm模块,则可以使用type-fest
:
import {PromiseValue} from 'type-fest';
async promiseOne() {
return 1
} // => () => Promise<number>
PromiseValue<promiseOne()>
//=> number
答案 3 :(得分:3)
计划实施此功能的Typescript 3.9。不幸的是,它已经被移回了,它可能是4.0版本。
新类型将称为awaited
。由于向后兼容性问题,它被延迟了。
答案 4 :(得分:2)
一个老问题,但是我想加2美分。使用Promise
类型来解约是很方便的,但是我发现我通常很想像await
运算符一样来弄清楚“ thenable”对象的值。
为此,我写了一个Await<T>
助手,它可以解开promise和随后的对象:
type Await<T> = T extends {
then(onfulfilled?: (value: infer U) => unknown): unknown;
} ? U : T;
答案 5 :(得分:1)
import {C} from 'ts-toolbelt'
const promise = new Promise<string>((res, rej) => res('x'))
type test0 = C.PromiseOf<typeof promise> // string
type test1 = C.PromiseOf<Promise<number>> // number
答案 6 :(得分:1)
我们可以通过查看 Promise 的 then
函数的参数来推断类型。
type PromisedString = Promise<string>;
type AwaitedPromisedString = Parameters<Parameters<PromisedString['then']>[0] & {}>[0];
const promisedString: PromisedString = Promise.resolve('sup');
const x: AwaitedPromisedString = await promisedString;
// assignment succeeds!
const y: string = x;
我们可以概括为一个实用程序类型:
type Awaited<T extends Promise<unknown>> = Parameters<Parameters<T['then']>[0] & {}>[0];
const promisedString: Promise<string> = Promise.resolve('sup');
const x: Awaited<typeof promisedString> = await promisedString;
const y: string = x;
让我们分解一下:
Promise<string>['then']
一个接受回调的函数。让我们获取该函数的参数。
Parameters<Promise<string>['then']>[0]
then
的第一个参数:它的回调。这是可选的,因此我们需要将联合范围缩小到仅真实类型。
Parameters<Promise<string>['then']>[0] & {}
回调本身。这是一个函数;让我们获取它的参数。
Parameters<Parameters<Promise<string>['then']>[0] & {}>[0]
回调的第一个参数:Promise 解析的值。这就是我们要找的。p>
鉴于上述条件类型,也许这个答案似乎是多余的,但我发现它对于解决 JSDoc 中的 Promises 很有用,在那里(我认为)不可能定义新的实用程序类型,但 是 可以使用现有的:
/** @param {Parameters<Parameters<ReturnType<import('box2d-wasm')>['then']>[0] & {}>[0]} box2D */
export const demo = box2D => {
};
答案 7 :(得分:0)
Promise
类型中没有任何内容允许访问或提取其值的类型。你必须找到一种使用类型推断的间接方式。
一个选项是将promiseOne
作为独立函数作为类构造函数的参数传递,并且类本身是通用的。然后编译器能够从promise类型中推断出值类型:
async function promiseOne() {
return 1
} // => Promise<number>
class C<T> {
constructor(private p: () => Promise<T>) {
p().then(value => this.pValue = value)
}
pValue: T | undefined = undefined;
}
const c = new C(promiseOne); // at compile time, typeof c is C<number>