首页 > 解决方案 > 在打字稿中,是否可以为 Function.prototype.bind polyfill 正确定义类型?

问题描述

我需要为 Function.prototype.bind 实现一个 polyfill,类似于以下内容:

function functionBind(fn, scope, ...bindArgs) {
    return function (...args) {
        const boundArgs = bindArgs || [];
        const callerArgs = Array.prototype.slice.call(arguments) || [];

        return fn.apply(scope, boundArgs.concat(callerArgs));
    };
}

但是,我很难为此实现正确的类型。最后,我需要将给定函数的参数作为元组的东西,并且从那个元组中,我需要一个在开头丢失一些条目的类型(取决于为绑定函数提供了多少参数),为结果函数返回正确的类型。

有没有办法得到像部分元组这样的东西?甚至可以正确键入此函数,尤其是在启用所有严格的编译器选项的情况下?

标签: typescript

解决方案


没有从元组中取出项目的好方法(有递归条件类型解决方案,但我不一定会使用它们)。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

游乐场链接


推荐阅读