...args 的通用类型?

generic type for ...args?

我有一个函数time

const time = <T>(fn: (...args: any[]) => Promise<T>, ...args: any[]): Promise<T> => {
  return new Promise(async (resolve, reject) => {
    const timer = setTimeout(() => reject(`Error: ${fn.name} timed out`), ms)
    try {
      resolve(await fn.bind(thisArg)(...args))
    } catch(err) {
      reject(err)
    } finally {
      clearTimeout(timer)
    }
  })
}

我想知道是否有办法避免使用 any 作为 ...args 的类型?特别是因为我想将 fn 签名 (fn: (...args: any[]) => Promise<T>) 中 ...args 的类型与 ...args 的类型(time 函数的第二个参数).这两个 ...args 是相同的参数,因此它们似乎应该通过泛型关联起来。我想到了这样的事情:

const time = <T, U>(fn: (...args: U[]) => Promise<T>, ...args: U[]): Promise<T>

但这似乎是错误的,因为参数不会都是同一类型。相反,无论 fn 签名中 ...args 的类型是什么,也将是 time 函数的第二个参数 ...args 的类型。

我们可以这样做:

const time = <T, U extends unknown[]>(fn: (...args: U) => Promise<T>, ...args: U): Promise<T>

Playground Link

the arguments will not all be of the same type

...args 的类型确实必须是 array/tuple,因为它使用了剩余运算符。

但不是键入 U[],这确实强制每个单独的参数都是类型 U,我们可以简单地使用泛型键入整个数组,前提是它被限制为一个数组:U extends unknown[] 现在我们可以做 ...args: U