I want wrap callback function and extend custom arguments, And i get error type alert
const func = (a: string) => {
console.log(a);
}
type Options = {
force?: boolean
};
const wrapFunc = <A extends any[], R>(fn: (...args: A) => R) => {
const wrappedFunc = (...args: A & [options?: Options]) => {
const options: Options = 'force' in args[args.length - 1] ? args.pop() : {};
fn(...(args as A))
}
return wrappedFunc;
}
const newFunc = wrapFunc(func);
newFunc('a', {force: true})
// Argument of type '["a", { force: true; }]' is not assignable to parameter of type '[a: string] & // [options?: Options | undefined]'.
// Type '["a", { force: true; }]' is not assignable to type '[a: string]'.
// Source has 2 element(s) but target allows only 1.(2345)
here is reproduced TypeScript playground
Could somebody help me make is right. Thanks!
The
&operator is not what you should use.number[] & {prop: string}will expect an array with apropproperty typed as astring, not another element. To push an element to a generic array parameter, you can do as follows:<A extends unknown[]>(args: [...A, Options]This one isn't suitable for us since we want to have optional options, and it can be achieved by telling the compiler that we expect
AorAwith options:Implementation:
This works as expected; however, the label of
ais removed in the hinting when you also acceptOptions. To fix it, we should use labeled tuples as follows:This way hinting will be better:
playground
Note: You can also consider using the following approach, however, it may throw some Typescript errors depending on your tsconfig: