Repository navigation
New syntax for advanced typing array of arguments #33778
Description
Activity
sviat9440 commented
on Oct 3, 2019 ContributorAuthorMore actionsRest arguments and tuple types?
sviat9440 commented
on Oct 3, 2019 ContributorAuthorMore actionsI'm on mobile, so, I'm not too sure if this would work but your Promise.all thing can probably be written with far fewer overloads,
//We want T to distribute type UnwrapPromiseLike<T> = T extends PromiseLike<infer U> ? U : T; //snip //for empty tuple all (arr : []) : Promise<[]>; //for non-empty tuple all<ArrT extends any[]> (arr : ArrT & {"0":any}) : Promise<{ [i in keyof ArrT] : UnwrapPromiseLike<ArrT[i]> }>; //for non-tuple array all<ArrT extends any[]> (arr : ArrT) : Promise<{ [i in keyof ArrT] : UnwrapPromiseLike<ArrT[i]> }>;
The idea is that we use
{"0":any}to make TS infer a non-empty tuple of arbitrary length. Then, we use a mapped type to return a tuple with theawait'd types.We place the "regular array" overload after the tuple overload as a fallback. It does the same thing as the tuple overload but you get back a regular array instead.
The empty tuple overload is for the empty tuple case.
Again, I'm typing all this on mobile so I'm not 100% if the above construction will work but it should be possible to get it working with some tweaking if I've messed up.
However, if you have rest arguments, your life should be much easier.
//We want T to distribute type UnwrapPromiseLike<T> = T extends PromiseLike<infer U> ? U : T; //snip //should handle empty tuple, non-empty tuple, and regular arrays all<ArrT extends any[]> (...arr : ArrT) : Promise<{ [i in keyof ArrT] : UnwrapPromiseLike<ArrT[i]> }>;
Reacted by Sviatoslav Zaytsevsviat9440 commented
on Oct 3, 2019 ContributorAuthorMore actionsAnyhowStep Promise.all is a method of Typescript npm lib. It is not my method.
File: lib.es2015.promise.d.ts.
I mentioned this to have more than one example of use.But I will try to apply your solution in my case. Thank you!)
I know. I'm just saying it can be written to handle tuples of arbitrary length.
We don't really need new special syntax to handle variable argument generic types because we have tuple types and array/tuple mapped types now.
TS also somewhat unofficially supports recursive types right now, which can be used for pretty insane type level operations.
And it will get more official support for recursive types with 3.7.
I'm not entirely sure how thorough the new official support will be, though.
TL;DR, tuple types, rest args, mapped array types, tuple-inference for non-rest arg, recursive type aliases = no real need for variable type argument support
sviat9440 commented
on Oct 3, 2019 ContributorAuthorMore actionsAnyhowStep Is it possible to implement something like Union type, from the first example?
What you're looking for is
UnionToIntersection<U>.https://github.com/AnyhowStep/type-mapping/blob/master/src/type-util/union-to-intersection.ts
type Foo = [string, number]; //string & number type Bar = UnionToIntersection<Foo[number]>;
Reacted by Sviatoslav Zaytsev- addedAwaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScriptAn idea for TypeScript
on Oct 17, 2019 Copy-pasting my comment on #33707 over here.
This is better,
type Awaited<T> = T extends undefined ? T : T extends PromiseLike<infer U> ? U : T ; declare function all<T extends readonly any[]>( values: T ): Promise<{ -readonly [P in keyof T]: Awaited<T[P]> }>; declare const numArr: number[]; //const newAll0: Promise<never[]> const newAll0 = all([]); //const newAll1: Promise<(string | number | boolean)[]> const newAll1 = all([1, "2", true]); //const newAll2: Promise<number[]> const newAll2 = all(numArr); //const curAll0: Promise<never[]> const curAll0 = Promise.all([]); //const curAll1: Promise<(string | number | boolean)[]> const curAll1 = Promise.all([1, "2", true]); //const curAll2: Promise<number[]> const curAll2 = Promise.all(numArr); //for empty tuple declare function betterAll (arr : []) : Promise<[]>; //for non-empty tuple declare function betterAll<ArrT extends readonly [any, ...any[]]>( arr: ArrT ): Promise<{ -readonly [i in keyof ArrT]: Awaited<ArrT[i]> }>; //for non-tuple array declare function betterAll<ArrT extends readonly any[]>( arr: ArrT ): Promise<{ -readonly [i in keyof ArrT]: Awaited<ArrT[i]> }>; //const betterAll0: Promise<[]> const betterAll0 = betterAll([]); //const betterAll1: Promise<[number, string, boolean]> const betterAll1 = betterAll([1, "2", true]); //const betterAll2: Promise<number[]> const betterAll2 = betterAll(numArr);
See
all(this PR) vsPromise.all(current impl) vsbetterAll(mine)Reacted by Sviatoslav Zaytsev and Toni Villenasviat9440 commented
on Nov 6, 2019 ContributorAuthorMore actionsThank you for solution. It's really helps me!
Reacted by Toni Villena

Search Terms
new syntax, advanced types, generic, array of arguments
Suggestion
Hi, everybody!
I think it would be cool to create a solution to this problem.
If you want to control the typing of the result of a function based on an unlimited number of incoming arguments, you will need a huge number of overloads.
Use Cases
For example, you have a class that contains a property configuration:
Next, create several inheritors of constructors:
Next, create function, that will build class with property configs:
And create some instances of PropertyConfiguration:
Funnaly, Let's try to apply it:
It's works! But, very uncomfortable and ugly. For example if you want to create class with ten properties, you need to implement corresponded overloads.
Examples
As I see the solution to this problem:
Checklist
My suggestion meets these guidelines: