TypeScript 3中的扩展元组?

时间:2018-08-22 19:26:02

标签: typescript

TypeScript 3带来了一项新功能,即元组的扩展,可以使用任何类型的rest参数。

它看起来像这样:

function call<TS extends any[], R>(fn: (...args: TS) => R, ...args: TS): R {
    return fn(...args);
}

function foo(x: number, y: string): string {
    return (x + y).toLowerCase();
}

// The `TS` type parameter is inferred as `[number, string]`
let a = call(foo, 100, "Hello");

console.log(a);

使用它的主要原因是什么,我无法理解此代码的优势

如我所知,它允许传递任何参数以使用任何类型的函数。

为什么不使用简单的方法,它会得到相同的结果:

function call(fn, ...args) {
    return fn(...args);
}
function foo(x: number, y: string, z: string): string {
    return (x + y + z).toLowerCase();
}

// The `TS` type parameter is inferred as `[number, string]`
let a = call(foo, 100, "Hello", "sss");

console.log(a);

我认为在这方面有优势

function call<TS extends number[], R>(fn: (...args: TS) => R, ...args: TS): R {
    return fn(...args);
}

function foo(x: number, y: number):number {
    return x + y;
}

function foo2(x: number):number {
    return x;
}

// The `TS` type parameter is inferred as `[number, string]`

let a = call((x: number, y: number) => x + y, 1, 2);
let b = call((x: number) => x, 1);

console.log(a);
console.log(b);

当TypeScript自动了解哪个函数调用取决于参数时。

1 个答案:

答案 0 :(得分:2)

有关更多信息,请参见TypeScript documentationrelevant pull request介绍此功能。自2015年以来,TypeScript中就出现了open feature request,受到了数百人的欢迎,因为它具有处理未指定长度的元组类型(也称为“可变类型”)的能力。

许多链接文档中都引用了为什么要这样做的简短答案:

  

借助这些功能,可以强有力地键入许多转换函数及其参数列表的高阶函数。

在您的示例中,

function call<TS extends any[], R>(fn: (...args: TS) => R, ...args: TS): R {
    return fn(...args);
}

call()接受一个函数和适合该函数的参数列表。如此有效:

call((x: number, y: number) => x + y, 1, 2);

但是这些不是:

call((x: number, y: number) => x + y, 1); // error
call((x: number, y: number) => x + y, 1, "whoops"); // error

如果没有元组的休息/散布,则只能使用一大堆overloads进行强力键入,这既乏味又脆弱:

function call<R>(fn: () => R): R;
function call<T0, R>(fn: (t0: T0) => R, t0: T0): R;
function call<T0, T1, R>(fn: (t0: T0, t1: T1) => R, t0: T0, t1: T1): R;
function call<T0, T1, T2, R>(fn: (t0: T0, t1: T1, t2: T2) => R, t0: T0, t1: T1, t2: T2): R;
// ... more more more 
function call(fn: Function, ...args: any[]): any {
  return fn(...args);
}

无论如何,如果您觉得它没有用,请不要使用它。它将最常用于库或其他类型操作很重要的地方。

希望有帮助。祝你好运!