2017-01-16 63 views
0

我试图创建一个拦截器函数。在我的具体情况下,一个油门功能。返回与接收到的函数签名相同的函数

请看下面的例子:

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; 
    }; 
} 

此功能将首先调用由参数传递的功能,并且不会再次调用它,直到指定等待时间已经达到或目标函数的参数改变。

这样做的问题是它应该返回与参数传入的函数相同的函数类型,所以它对调用者可以是透明的。

举例来说,这应该是允许的,但它不是:

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); 

我怎样才能做到这一点?

回答

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