如何使 TypeScript 从数组中推断参数的数量和类型

Posted

技术标签:

【中文标题】如何使 TypeScript 从数组中推断参数的数量和类型【英文标题】:How to make TypeScript infer number & types of arguments from an array 【发布时间】:2021-05-03 17:58:37 【问题描述】:

我尝试创建一个简单的函数来接受:

    回调 要传递给回调的可选参数数组

普通 JS 中的函数如下所示:

const callCallback = (cb, args = []) => cb(...args);

回调可能接受任意数量的参数并返回任何值。问题是我无法用 TypeScript 正确表达回调的类型。我试图像这样声明callCallback 的类型(想法是推断回调的参数和返回类型):

export interface CallCallback 
  <CbReturn, CbArgs>(
    cb: (...optionalArguments: CbArgs[]),
    args?: CbArgs[],
  ): CbReturn
;

但是,这不起作用,因为它强制回调使用参数传播语法,而这不是我打算做的。

我还找到了this answer,但目前 TS 不允许我将扩展参数设为可选。

如何将args 的数字和类型推断到cb 参数列表中?

【问题讨论】:

【参考方案1】:

下面的方法有用吗?看来您实际上是在输入apply:

interface ApplyFn 
    <F extends () => any>(fn: F): ReturnType<F>;
    <F extends (...args: any[]) => any>(fn: F, args: Parameters<F>): ReturnType<F>;


declare const apply: ApplyFn;

apply((f: number, s: string, t: Date) => f + s + t, [23, "two", new Date]); // OK
apply((f: number, s: string, t: Date) => f + s + t, ["not a number", "two", new Date]); // ERR
apply((f: number, s: string, t: Date) => f + s + t, [123, "two"]); // ERR

apply(() => "nice!", []); // OK
apply(() => "nice!"); // OK
apply((param: number) => "nice!"); // ERR

编辑:如果您有适合此类函数的孔(例如,函数参数),则上述类型很有用。如果您实际上是在尝试定义此函数,则将其表示为标准函数定义会更容易:

function apply<F extends () => any>(fn: F): ReturnType<F>;
function apply<F extends (...args: any[]) => any>(fn: F, args: Parameters<F>): ReturnType<F>;
function apply(fn: Function, args: any[] = []) 
  return fn(args);

【讨论】:

非常感谢!我不完全了解它是如何工作的,因为它对我来说太先进了,但你的回答肯定有很大帮助。 不明白的地方欢迎指出,我会扩大答案。 那太好了,首先,您能否在答案中添加一个实际的函数声明?因为declare const callCallback: ApplyFn = (fn, args = []) =&gt; fn(...args); 产生类型错误&我不知道如何应用ApplyFn 类型。 我在TS中添加了写实际函数的最简单的方法。

以上是关于如何使 TypeScript 从数组中推断参数的数量和类型的主要内容,如果未能解决你的问题,请参考以下文章

在 TypeScript 中,如何在具有多个类型参数的方法中推断出泛型类型参数?

TypeScript 是不是可以从动态对象中推断出键?

从类型的默认参数推断 TypeScript 类型

如何使 TypeScript 字符串枚举适用于字符串文字并正确进行类型推断

typescript 从子类调用的构造函数参数推断类型

Typescript 推断的泛型类型在条件类型中是未知的