有没有办法在Typescript中的包装函数中动态键入函数?

时间:2019-03-11 15:31:43

标签: javascript typescript function types metaprogramming

所以说我有一个简单的用例-我想将一个函数包装在另一个时间跟踪函数中。我不想在任何地方都复制粘贴时间跟踪代码,而是想通过围绕原始函数创建包装函数并创建一个新函数来抽象时间跟踪代码。因此,我最终得到了如下所示的功能。

function wrapFunction(someFunction: Function) {
  const wrappedFunction = function() {
    let args = arguments;
    let beforeTime = new Date();
    someFunction.apply(args);
    let afterTime = new Date();
    console.log("Time Elapsed " + afterTime - beforeTime);
  };
  return {execute: wrappedFunction};
}

然后使用它,我将执行以下操作:

//Generate the wrapped function
let wrappedFunction = wrapFunction((param1 : string, param2: number) =>{
  console.log("Param1 = ", param1);
  console.log("Param2 = ", param2);
});
//This is the actual usage of the function
wrappedFunction.execute('param1', 2);

我的问题是:有没有一种方法可以动态设置返回的.execute()的函数参数,而Typescript可以检测错误,而IDE可以选择函数参数。

在当前状态下,如果不检查函数的生成位置,我无法检查应将哪些参数传递给.execute()。

2 个答案:

答案 0 :(得分:3)

您可以在rest参数中使用泛型和元组:

function wrapFunction<A extends any[], R>(someFunction: (...a: A) => R) {
    const wrappedFunction = function (...args: A) {
        let beforeTime = new Date();
        let result = someFunction(...args);
        let afterTime = new Date();
        console.log("Time Elapsed " + (afterTime.getDate() - beforeTime.getDate()));
        return result;
    };
    return { execute: wrappedFunction };
}

//Generate the wrapped function
let wrappedFunction = wrapFunction((param1: string, param2: number) => {
    console.log("Param1 = ", param1);
    console.log("Param2 = ", param2);
});

wrappedFunction.execute('param1', 2); //ok now

答案 1 :(得分:2)

是的,请使用通用函数类型:

function wrapFunction<F extends Function>(someFunction: F) {
  function wrappedFunction(...args) { // personal preference + performance boost
    const beforeTime = new Date();
    const result = someFunction.apply(this, args);
    const afterTime = new Date();
    console.log("Time Elapsed " + afterTime - beforeTime);
    return result;
  }

  return {execute: wrappedFunction as F }; // why this object though?
}