2017-01-16 6 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

関連する問題