Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type-challenges-solutions/en/medium-promise-all #237

Open
utterances-bot opened this issue Aug 1, 2022 · 8 comments
Open

type-challenges-solutions/en/medium-promise-all #237

utterances-bot opened this issue Aug 1, 2022 · 8 comments

Comments

@utterances-bot
Copy link

Promise.all

This project is aimed at helping you better understand how the type system works, writing your own utilities, or just having fun with the challenges.

https://ghaiklor.github.io/type-challenges-solutions/en/medium-promise-all.html

Copy link

muzichen commented Aug 1, 2022

I dont understand the <{ [P in keyof T]: T[P] extends Promise<infer R> ? R : T[P] }> part, the keyof operator can also be used to iterate tuple types?

Copy link
Owner

ghaiklor commented Aug 2, 2022

@muzichen short version – yes.

Long version... Let's take a [1, 2, 3] tuple and provide it as is to the type:

type Demo<T> = T
type R0 = Demo<[1, 2, 3]> // type R0 = [1, 2, 3]

When adding a keyof operator, you will get a union of “indexes” of the tuple:

type Demo<T> = keyof T
type R0 = Demo<[1, 2, 3]> // type R0 = keyof [1, 2, 3]

Once we add it to mapped types, what we do is “take keys of the tuple and for each key written into I do this”:

type Demo<T> = { [I in keyof T]: T[I] }
type R0 = Demo<[1, 2, 3]> // type R0 = [1, 2, 3]

In this example above, what happened is we copied the tuple. Because we took all the keys from the original one and for each key in there took its value.

It is a bit unintuitive, but it works. The thing is that “keys” we are working with here are indexes of the tuple, not the object.

Copy link

new test case has been added and this solution is failed. can you update the solution, please?

@ghaiklor
Copy link
Owner

@dianrahmaji try to solve it and feel free to leave a comment with the updated solution for other people to see.

Copy link

sure. this is the solution that pass all the test cases using a helper type.

type MyAwaited<T> = T extends PromiseLike<infer R> ? MyAwaited<R> : T

declare function PromiseAll<T extends any[]>(values: readonly [...T]): Promise<{
  [P in keyof T]: MyAwaited<T[P]>
}>

@HenryZhang-ZHY
Copy link

HenryZhang-ZHY commented Jun 1, 2023

sure. this is the solution that pass all the test cases using a helper type.

type MyAwaited<T> = T extends PromiseLike<infer R> ? MyAwaited<R> : T

declare function PromiseAll<T extends any[]>(values: readonly [...T]): Promise<{
  [P in keyof T]: MyAwaited<T[P]>
}>

Could you explain why?
Why did ghaiklor's solution fail and how did you manage to fix it?
How can I better understand it?

Copy link

@imentu
The test 4 failed because it transfer the generic。
think about this type:

type a<T> = {[p in keyof T]: T[p] extends Promise<infer R>? R: T[p]};
type b = a<Array<number|Promise<number>>>

The b is (number | Promise<number>)[], so the problem is the T[p].

Copy link

mPyth commented Apr 18, 2024

Here is solution without using mapping types. It uses helper type PromiseAllType:

type PromiseAllType<A extends any[], Acc extends any[] = []> =
  A extends [infer FirstElem, ... infer Rest]
  ? PromiseAllType<Rest, [...Acc, Awaited<FirstElem>]>
  : Promise<Acc>
;

declare function PromiseAll<T extends unknown[]>(
  values: readonly [...T],
): PromiseAllType<T>;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants