【问题标题】:TypeScript - typing rest parameters and return values when wrapping a functionTypeScript - 包装函数时输入剩余参数和返回值
【发布时间】:2021-05-03 14:56:13
【问题描述】:

我想创建一个包装任意函数的函数,但对参数和结果保持相同的类型。例如,这将包装一个函数 - 但类型将变为 any

// Note that the returned wrappedFn takes the same arguments as fn, and returns
// a value of the same type as the one returned by fn.
function myWrapper(fn: (...args: any[]) => any): (...args: any[]) => any {
  return function wrappedFn(...args: any[]) {
    // ...some arbitrary code goes here
    return fn(...args);
  };
}

function repeatString(str: string, times: number): string {
  return Array(times + 1).join(str);
}

// TS is aware that wrappedRepeatString is a function, but it infers that
// it takes any parameters, rather than a string and a number.
const wrappedRepeatString = myWrapper(repeatString);

// The result of this call is "foofoofoo" (a string), but TS sees it as "any".
const repeatedString = wrappedRepeatString("foo", 3);

// Since repeatedString is of type "any", this compiles, even though
// it'd crash as there's no "toFixed" method on strings.
repeatedString.toFixed();

我可以输入 myWrapper 来获取一个函数,该函数接受一个字符串和一个数字作为参数,并返回一个数字 - 但如果我想将它与具有不同参数或返回类型的函数一起使用,我需要再写一个。理想情况下,我可以编写一个包装器,使 TS 能够推断出wrappedFn(返回的函数)的参数和返回值与`fn 的相同。

请注意,仅将其余参数输入为数组类型(例如 ...args: string[])是行不通的,因为参数也可能属于不同的类型。

【问题讨论】:

  • 对不起,我不明白这个问题。您能否提供没有错误的代码示例?
  • 我的错。我已经修改了代码并对问题给出了更清晰的描述。 (我希望。)

标签: typescript typescript-generics


【解决方案1】:

您可以使用泛型变量来描述函数fn,并要求组合函数具有相同的签名。

以函数为泛型,利用内置的实用程序类型ReturnType<T>Parameters<T>

function myWrapper<F extends (...args: any[]) => any>(fn: F) {
  return function wrappedFn(...args: Parameters<F>): ReturnType<F> {
    return fn(...args);
  };
}

请注意,虽然组合函数具有与 F 相同的参数并返回,但它不能完全分配给 F,因为 javascript 中的函数是对象,因此 F 类型可能包含一些任意额外的组合函数不具备的属性。

ArgsReturn 类型作为两个独立的泛型:

function myWrapper<Args extends any[], Return>(fn: (...args: Args) => Return) {
  return function wrappedFn(...args: Args): Return {
    return fn(...args);
  };
}

这两个都在repeatedString.toFixed() 上给出了所需的错误,因为repeatedString 的类型现在是string 而不是any

【讨论】:

  • 太棒了,这对我有用。 :) 非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 1970-01-01
  • 2019-06-07
  • 2019-12-31
  • 2014-01-31
  • 2019-08-02
相关资源
最近更新 更多