How to type combinePromise function in typescript

时间:2018-12-05 18:05:24

标签: typescript promise typescript-typings

I have this existing JS function, which is an alternative interface to Promise.all(). Is there a way to type it with TS?

// Like Promise.all() but taking an object<key,promise<?>> and returning object<key,promiseValue>
export const combinePromises = obj => {
   const keys = Object.keys(obj);
   const values = Object.values(obj);
   return Promise.all(values).then(results => {
      const combinedResult = {};
      results.forEach((result, i) => {
         const key = keys[i];
         combinedResult[key] = result;
      });
      return combinedResult;
   });
};

I'd like to be able to do

const {user,company} = await combinePromises({
    user: fetchUser(), 
    company: fetchCompany()
});

Given the fetch functions are typed, I expect the response (user and company) to be typed as well.

2 个答案:

答案 0 :(得分:2)

首先,请注意combinePromises必须返回一个Promise,因为Promise.all返回一个Promise。

function combinePromises(obj): Promise<...>

现在,...中需要做什么?好吧,您希望结果基本上与传入的对象相同,但是值已解析。

强制执行相同的键

要强制返回的值与传入的值具有相同的键,您需要使用泛型和keyof运算符:

type MyType<T> = { [K in keyof T]: ... };
function combinePromises<T>(obj: T): Promise<MyType<T>>

现在,在await的结果combinePromises之后,您将拥有一个对象,其键与传入对象的键相同。

强制执行类似的值

第二部分比较棘手,因为您不能解开Promise来获取内部类型。但是,您可以定义一个conditional type来推断提供给Promise<...>的内容的类型:

type ThenArg<T> = T extends Promise<infer U> ? U : any;

该定义意味着,如果可以将提供给T的类型ThenArg<...>分配给Promise<infer U>,则返回类型U。否则,默认输入any

因此ThenArg<Promise<User>>将返回User

您的最终类型定义和函数签名应如下所示:

type MyType<T> = { [K in keyof T]: ThenArg<T[K]> }; // T[K] is the Promise value of the object passed in
type ThenArg<T> = T extends Promise<infer U> ? U : any;

function combinePromises<T>(obj: T): Promise<MyType<T>>

combinedResult声明应类似于:

const combinedResult: MyType<T> = {} as MyType<T>;

同一类型的对象只是没有Promise层,因为在Promise.all的{​​{1}}内部,它们已经被解析。


完整的解决方案如下所示:

then

答案 1 :(得分:0)

我刚刚做到了:

const [ user, company ] = await Promise.all([
  fetchUser(),
  fetchCompany()
]);

并找到正确的类型。

https://stackblitz.com/edit/typescript-combine-promise-typed

编辑:

这不是一个好的答案,因为它不能直接回答OP问题。但这可能对其他人有益,因为您知道您可以以这种方式使用Promise.all。也许OP可以考虑直接使用Promise.all