-
-
Notifications
You must be signed in to change notification settings - Fork 21
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
Here's a generic function:
/**
* Call two functions with the same args, e.g.
*
* onClick={both(action('click'), setState)}
*/
export function both<
Args extends unknown[],
CB1 extends (...args: Args) => void,
CB2 extends (...args: Args) => void
>(fn1: CB1, fn2: CB2): (...args: Args) => void {
// See https://stackoverflow.com/a/62093430/388951
return function (...args: Args) {
fn1(...args);
fn2(...args);
};
}
I think this is fine in terms of every type parameter appearing multiple times. Args
only appears in other extends
clauses, but it can still be inferred. Here's an example of it being used, with all the parameters inferred:
const noop = () => {};
const fnWithCallback = (cb: (a: string, b: number) => void) => _.noop;
fnWithCallback(
both((a, b) => {
a; // type is string
b; // type is number
return a * b; // error
}, _.noop),
);
Mousing over both
in that example, I see:
const both: <[string, number], (a: string, b: number) => number, (...args: any[]) => void>(fn1: (a: string, b: number) => number, fn2: (...args: any[]) => void) => (a: string, b: number) => void
In other words, Args
is very much inferred.
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request