为什么Array.concat方法在TypeScript中定义了两次?

zpgglvta  于 2023-11-20  发布在  TypeScript
关注(0)|答案(2)|浏览(144)

我注意到TypeScript中的Array.concat方法在语言的官方类型定义文件中定义了两次。下面是该方法的定义:

/**
 * Combines two or more arrays.
 * This method returns a new array without modifying any existing arrays.
 * @param items Additional arrays and/or items to add to the end of the array.
 */
concat(...items: ConcatArray<T>[]): T[];

/**
 * Combines two or more arrays.
 * This method returns a new array without modifying any existing arrays.
 * @param items Additional arrays and/or items to add to the end of the array.
 */
concat(...items: (T | ConcatArray<T>)[]): T[];

字符串
我很好奇为何要重复界定,以及两个定义是否有分别,请问有没有人可以解释为何会重复界定,以及如果有分别的话,可否澄清?

1szpjjfi

1szpjjfi1#

我研究了这个问题,它看起来像是一个历史问题的遗留问题,与今天没有直接关系。在某个时候(TypeScript 2.0-ish),TypeScript对Array.prototype.concat()的声明有一个单一的调用签名来解释输入中的单个元素和数组(因为这表现得不同):

interface Array<T> {
  concat(...items: (T | T[])[]): T[];
}

字符串
但是当内部元素是元组类型时,这会产生一个问题,导致在microsoft/TypeScript#9901上的错误报告,其中

var a : Array<[number, number]>= [[1, 2]];
a.concat([[3, 4], [5, 6], [7, 8]]); // error!


会失败,因为编译器将[3, 4][5, 6]视为类型number[],而[7, 8]是预期的[number, number]T | T[]在面对元组时会使编译器感到困惑。他们决定修复方法是添加一个重载(实际上是“重新添加”一个重载,你可以自己在GitHub上研究完整的疯狂历史)在尝试处理混合数组之前,它首先尝试将输入视为单个数组类型。这在microsoft/TypeScript#9997中完成,导致这对签名:

interface Array<T> {
  concat(...items: T[][]): T[];
  concat(...items: (T | T[])[]): T[];
}


这解决了问题。
从那时起,发生了一些变化:

这导致了当前的签名:

interface Array<T> {
  concat(...items: ConcatArray<T>[]): T[];
  concat(...items: (T | ConcatArray<T>)[]): T[];
}


从历史的Angular 来看,这就是“原因”。从概念上讲,你应该只需要第二个调用签名,但第一个是为了解决一个bug而添加的。
问题是,即使你删除了第一个调用签名,这个bug似乎也不存在了:

interface MyArray<T> {
    // concat(...items: ConcatArray<T>[]): T[];
    concat(...items: (T | ConcatArray<T>)[]): T[];
}

declare const a: MyArray<[number, number]>;
const r = a.concat([[3, 4], [5, 6], [7, 8]]); // okay
// const r: [number, number][]


我假设自TypeScript 2.0以来,一些元组处理发生了重大变化。因此,在这一点上,可能没有任何理由存在第一个调用签名。感兴趣的一方可能想提出一个GitHub问题,要求将其删除。这样的问题可能会受到欢迎,也可能不会受到欢迎;破坏concat()的稳定性可能会带来更多的麻烦,但这超出了所问问题的范围,所以我将就此结束。
Playground链接到代码

fd3cxomn

fd3cxomn2#

Array.concat方法在TypeScript中没有定义两次;它只有一个定义。它是标准JavaScript Array原型的一部分,也可以在TypeScript中访问。
如果有重复的感觉,可能是因为TypeScript为JavaScript方法提供了类型注解,这些注解是TypeScript标准库声明的一部分。然而,Array.concat的实际实现是JavaScript运行时的一部分,TypeScript继承并扩展了这些类型。
要在TypeScript中使用Array.concat,您可能会看到如下类型注解:

concat<T>(...items: (T | ConcatArray<T>)[]): T[];

字符串

相关问题