-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
extract rest params #17898
extract rest params #17898
Conversation
Update: managed to make it error both if passing too many as well as if passing too few arguments now. That only leaves the hard part now... |
@tycho01 Here's another use case to check:
|
@eggers: out of curiosity, what's up with the |
@tycho01 I was looking for a way to ensure that T is an array to activate that signature. There's probably a better way. |
@eggers: Makes sense then. This wasn't a standard library function though is it? |
@tycho01 It's not in the native promise library, but it's in most polyfills. There are different ways of declaring spread now: // Q
spread<U>(onFulfill: (...args: any[]) => IWhenable<U>, onReject?: (reason: any) => IWhenable<U>): Promise<U>;
// bluebird
spread<U, W>(fulfilledHandler: (...values: W[]) => U | PromiseLike<U>): Bluebird<U>;
spread<U>(fulfilledHandler: Function): Bluebird<U>;
// When
spread<T>(onFulfilled: _.Fn0<Promise<T> | T>): Promise<T>;
spread<A1, T>(onFulfilled: _.Fn1<A1, Promise<T> | T>): Promise<T>;
spread<A1, A2, T>(onFulfilled: _.Fn2<A1, A2, Promise<T> | T>): Promise<T>;
spread<A1, A2, A3, T>(onFulfilled: _.Fn3<A1, A2, A3, Promise<T> | T>): Promise<T>;
spread<A1, A2, A3, A4, T>(onFulfilled: _.Fn4<A1, A2, A3, A4, Promise<T> | T>): Promise<T>;
spread<A1, A2, A3, A4, A5, T>(onFulfilled: _.Fn5<A1, A2, A3, A4, A5, Promise<T> | T>): Promise<T>; None of which will give an error if the fulfilled handler arguments are incompatible with the promise type. e.g.: declare var promise: Promise<number>;
promise.spread((x: string) => x); // No error |
@eggers: Thanks for the background, at least I know where to check for run-time behavior now. Your case here is actually interesting as you don't even require capturing the info into a generic for this -- with that, it appears to already work with my current progress :), just added a test for it. |
Awesome. I made some explicit use cases below. The second overload was to cover how I thought bluebird treated promises that aren't arrays (see case 1), but I retested, and it actually throws an error ( declare var promiseNumber: Promise<number>;
promiseNumber.spread((x: string) => x); // Case 0: Error
promiseNumber.spread((x: number) => x); // Case 1: No Error
declare var promiseNumberArray: Promise<number[]>;
promiseNumberArray.spread((x: string) => x); // Case 2: Error
promiseNumberArray.spread((x: number) => x); // Case 3: No Error
declare var promiseTuple: Promise<[number, string]>;
promiseTuple.spread((x: string, y: string) => x); // Case 4: Error
promiseTuple.spread((x: number, y: string) => x); // Case 5: No Error
promiseTuple.spread((x: number) => x); // Case 6: Probably Error, though not critical
promiseTuple.spread((x: number, ...rest: any[]) => x); // Case 7: No Error
promiseTuple.spread((...start: any[], x: string) => x); // Case 8: No Error |
9b6de0c
to
6d38c6b
Compare
I got this working now, would be happy to get feedback. |
Update: I fixed the test Travis complained about. Apparently the |
I ran into this recently with code like:
So looking forward to seeing this merged. |
Hi. Would this change allow me pass a callback function where i change the callback function's return type but keeping the parameters names and types? e.g. something like this:
would the signature of myPatchedFunction then be:
/Mikkel |
@MikkelSnitker: this PR does half of that. That The second part, the An alternative possible today would be to type |
@tycho01 Thanks for the clarification :) I don't see how I could overload the patchFunction, and keep the parameter names (it's meant to take an arbitrary function as input). In my use case the patchFunction would take a pure function and wrap it into a redux action, but still keep the parameter names/types of the original function. Are there any timeline for when we could expect this (and #18004 ) to be included in typescript? /Mikkel |
Yeah, state management libs like Redux are definitely one of the main use cases of type programming :), that was what drove me to wanting to see more progress on this front as well.
I haven't received feedback from the team on either here yet, seems they're quite busy.
I would love this as well. My current PRs don't cover param names though -- I don't know what would be the nicest API for this. I'd be pretty interested in ideas on that front. |
I'm not a language designer, but a could a simple solution be to make a generic function type? like
|
Note that for testing types in TS you can write The idea of a generic function type was discussed at gcanti/typelevel-ts#8, with an attempt at implementation on my part here. Note that using that in an attempt to capture the function is a bit problematic though -- I don't think you can currently use the type params in In fact, afaik we currently don't have a way to extract parameter types from function types at all, other than using overload matching (kills generics, verbose, doesn't scale well performance-wise once you get multiple variables that explode the number of combinations). I'd made a PoC to work around this for |
What's the status of that cool feature? |
Thanks for your contribution. This PR has not been updated in a while and cannot be automatically merged at the time being. For housekeeping purposes we are closing stale PRs. If you'd still like to continue working on this PR, please leave a message and one of the maintainers can reopen it. |
This stub to extracting rest params into tuple types is the second part of my attempt to tackle #5453.
It allows specifying array-like types including tuple types and array-bound generics as rest constraints:
<T extends number[]>(...args: T)
/(...args: [number, string])
. The former of these examples aims to extract the types of passed parameters on function application, while the latter is primarily useful to dynamically generate functions, e.g. to typebind
orcurry
.One may extract the types passed into generics from rest parameters as follows:
Fixes a third of #5453, alongside other issues that ran into
A rest parameter must be of an array type
, like #1024, #2328, #5331, and #16931.