Нет хорошего способа извлечь элемент из кортежа (есть рекурсивные решения условного типа, но я бы не обязательно их использовал). Способ bind
работает в машинописном тексте (когда --strictBindCallApply
включен) - это наличие нескольких перегрузок, до ряда параметров целесообразно привязать:
bind<T>(this: T, thisArg: ThisParameterType<T>): OmitThisParameter<T>;
bind<T, A0, A extends any[], R>(this: (this: T, arg0: A0, ...args: A) => R, thisArg: T, arg0: A0): (...args: A) => R;
bind<T, A0, A1, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1): (...args: A) => R;
bind<T, A0, A1, A2, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R;
bind<T, A0, A1, A2, A3, A extends any[], R>(this: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, thisArg: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R;
bind<T, AX, R>(this: (this: T, ...args: AX[]) => R, thisArg: T, ...args: AX[]): (...args: AX[]) => R;
Вы можете использовать аналогичный подход:
function functionBind<T>(fn: T, thisArg: ThisParameterType<T>): OmitThisParameter<T>;
function functionBind<T, A0, A extends any[], R>(fn: (this: T, arg0: A0, ...args: A) => R, scope: T, arg0: A0): (...args: A) => R;
function functionBind<T, A0, A1, A extends any[], R>(fn: (this: T, arg0: A0, arg1: A1, ...args: A) => R, scope: T, arg0: A0, arg1: A1): (...args: A) => R;
function functionBind<T, A0, A1, A2, A extends any[], R>(fn: (this: T, arg0: A0, arg1: A1, arg2: A2, ...args: A) => R, scope: T, arg0: A0, arg1: A1, arg2: A2): (...args: A) => R;
function functionBind<T, A0, A1, A2, A3, A extends any[], R>(fn: (this: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3, ...args: A) => R, scope: T, arg0: A0, arg1: A1, arg2: A2, arg3: A3): (...args: A) => R;
function functionBind<T, AX, R>(fn: (this: T, ...args: AX[]) => R, scope: T, ...args: AX[]): (...args: AX[]) => R;
function functionBind<T>(fn: (this: T, ...args: any[]) => any, scope: T, ...bindArgs: any[]) {
return function (...args: any[]) {
const boundArgs = bindArgs || [];
const callerArgs = Array.prototype.slice.call(arguments) || [];
return fn.apply(scope, boundArgs.concat(callerArgs));
};
}
function test(a: string, b: number) {
}
var r = functionBind(test, null, "") // (b: number) => void
Playground Link