返回与收到的函数签名相同的函数签名

时间:2017-01-16 18:11:27

标签: function generics typescript

我试图创建一个拦截器功能。在我的具体情况下,节流功能。

考虑以下示例:

function throttle(func: Function, wait: number = 0): Function {
    let previous: {
        args: any[];
        timestamp: number;
        result: any;
    } = {
        args: [],
        timestamp: 0,
        result: null
    };
    return (...currentArgs: any[]): any => {
        const now = Date.now();
        const remaining = wait && (wait - (now - previous.timestamp));
        const argumentsChanged = JSON.stringify(currentArgs) !== JSON.stringify(previous.args);
        if (argumentsChanged || (wait && (remaining <= 0 ||remaining > wait))) {
            previous = {
                args: currentArgs,
                timestamp: now,
                result: func.apply(this, currentArgs)
            };
        }
        return previous.result;
    };
}

此函数最初将调用由参数传递的函数,并且在达到指定的 wait 时间或目标函数的参数发生更改之前不会再次调用它。

这个问题是它应该返回与参数传入的函数相同的函数类型,因此它对调用者来说是透明的。

例如,应该允许这样做,但不是:

function updateStatus(id: number, newStatus: string): void {
  // ...
}

// ...

// Type 'Function' is not assignable to type '(id: number, newStatus: string) => void'
this.updateStatus = throttle(this.updateStatus.bind(this), 500);

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:0)

不使用Function类型,而是使用通用约束 函数签名应如下所示:

function throttle<T extends Function>(func: T, wait: number = 0): T

在一个简单的例子中:

function throttle<T extends Function>(func: T, wait: number = 0): T {
    return null;
}

function fn(a: string, b: number): boolean {
    return false;
}

let throttled = throttle(fn, 3); // type of throttled: (a: string, b: number) => boolean
throttled("stirng", 0); // ok
throttled(3, 4); // error: Argument of type '3' is not assignable to parameter of type 'string'

code in playground