-
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
fixed params last in variable argument functions #1360
Comments
I'm assuming by fixed arguments you mean required arguments since this certainly couldn't work when mixed with other rest params or optional arguments. While this proposal would work I'm not sure I see this adding enough value. Are there a lot of existing JavaScript APIs that would require this sort of signature? If not, this isn't really adding any expressivity or much convenience, just reordering some arguments in a subset of signatures that use rest params. Offhand I can't think of any other languages with varargs that support using them in any position but the last. |
A cataloging of libraries that use this pattern would be useful. |
One example is String.prototype.replace. Although this occurs in the middle and not exclusively at the beginning or end.
should be this:
|
I just came across this when updating TypeDefinitions for rethinkdb.
The problem here is For now I'm kind of "solving" it like
but this isn't just a pain to do, it's also not the representation of the underlying javascript library |
As mentioned in #3686, to add to the list of libraries doing this, lodash uses this pattern in extend/assign. I also want to call out that lodash makes the |
I'm getting stumped by something. Trying to create the typings for Flyd; it's a library that creates streams. It has a function const combinedSignal = flyd.combine(function(s1:Signal,s2:signal2,s3:signal3....,self:signal,changed:signal[]){}) I've tried the method described by @pgrm, but I'm getting It seems the method works as long as I don't have another interface with overload that uses an overloaded interface. But the library is entirely made of curried functions calling each other, I just can't not have overloads using overloads. I think I've managed to recreate a minimal test case here |
Same here. Considering this issue was first opened in Dec 2014, I think this should definitely be added in the near future! |
It looks like I wonder if allowing rest arguments in non-implementation signatures would be acceptable. That way we could potentially support this at the type level but we'd leave the runtime implementation to be decided by users. |
lodash 4 uses it for a number of functions: |
koa-router also uses fixed params after varargs: https://www.npmjs.com/package/koa-router#named-routes |
This has comes up a lot with certain style of function calling I've seen. The following is not possible as far as I'm aware, related to this issue. type FnWithCallbackAtEnd<
FnA extends Array<unknown>,
FnR extends unknown,
CbA extends Array<unknown>,
CbR extends unknown
> = (
...args: FnA,
cb: (...args: CbA) => CbR
) => FnR google api client library uses these types of callbacks, params where the last argument is a callback. In general the args are usually fixed, but I want to easily convert any callback function in this style into a promise. To do so, it'd be nice to maintain type safety throughout. |
Another use case: Jest |
Some personal use case here passing a context as last argument: https://stackblitz.com/edit/ts-with-rest-params |
FastCheck uses a callback at the end of the parameter list to define a property: https://cdn.jsdelivr.net/npm/fast-check@1.16.2/lib/types/check/property/Property.generated.d.ts Reversing the argument order could help but its problematic to do that with existing APIs: |
I was trying to make a function whose variable arguments are effectively a tuple of the same type, and I wanted to add an optional last parameter to allow a user to be able to optionally specify options on how to handle all the previous args (how to handle the tuple). F.e. someFunction(1,2,3,5,2,6,73,3,{method: 'factorial'}) I think the easiest solution, as I have the ability to modify the signature of the API, is to allow it to be called as someFunction(1,2,3,5,2,6,73,3) or someFunction([1,2,3,5,2,6,73,3], options) This is easy to do. Here's a playground example. |
Another way you can do it is to track a variable in the outer scope of your function. The call site would look like this: someFunction(1,2,3,5,2,6,73,3) or someFunction.callback = () => {...}
someFunction(1,2,3,5,2,6,73,3) But remember to make |
From https://nodejs.org/en/knowledge/getting-started/control-flow/what-are-callbacks/
Also there is The types for I wanted this feature for typing a decorator that takes a function with a callback (node style) and add the promise api if no callback is provided. Thus, the function is now retro-compatible with the callback call and as a promise with async/await. I wanted the types for the decorated function interface to be inferred from the original function. |
While I agree that this feature is very important and long overdue, there is a good reason not to implement it: It is not compatible with the ecmascript implementation of the rest spread operator. function x (a, ...b, c) {} results in an error like: |
But it still could be supported in function overloads and function types. |
it almost seems like this should be possible with the new Variadic Tuple Types releasing in 4.0? Messed around with it a bit, but couldn't get it. Attempt type StandardCallback<R> = (error: Error, result: R) => any
type Append<I, T extends unknown[]> = [...T, I]
function functionEndsWithCallback(...args: Append< StandardCallback<string>, unknown[]>){
}
functionEndsWithCallback(1, 2, (error) => {}); // not typesafe :( Update Go a response in this thread. As suspected, it can now be done! Related question/Answer on SO |
@RyanCavanaugh @andrewbranch this could be closed as it's currently possible with variadic tuple types. |
Thanks! |
Extracting this suggestion from this issue:
#1336
Currently the variable arguments list supports variable arguments only as the last argument to the function:
This compiles to the following javascript:
However, variable argument functions are limited to appearing only as the last argument and not the first argument. I propose support be added for having a variable argument appear first, followed by one or more fixed arguments:
subscribe compiles to the following JavaScript:
notes: it should be impossible for typescript code to call this function with zero arguments when typechecking. If JS or untyped TS code calls it without arguments, callback will be undefined. However, the same is true of fixed arguments at the beginning of the function.
edit: used a more realistic/motivating example for the fixed-last/variable-arguments-first function.
The text was updated successfully, but these errors were encountered: