48

代码比语言说得更好,所以:

['a', 'b', 'c'].reduce((accumulator, value) => accumulator.concat(value), []);

该代码非常愚蠢,并返回一个复制的数组......

TS 抱怨 concat 的参数:TS2345:“字符串”类型的参数不可分配给“ConcatArray”类型的参数。

4

4 回答 4

75

我相信这是因为 for 的类型[]被推断为never[],这是必须为空的数组的类型。您可以使用类型转换来解决此问题:

['a', 'b', 'c'].reduce((accumulator, value) => accumulator.concat(value), [] as string[]);

通常这不是什么大问题,因为 TypeScript 在根据您对空数组的处理方式找出更好的类型来分配给空数组方面做得不错。但是,由于您的示例正如您所说的那样“愚蠢”,因此 TypeScript 无法进行任何推断并将类型保留为never[].

于 2019-01-09T19:39:03.387 回答
24

一种更好的解决方案,可以避免两种变体中的类型断言(又名类型转换):

  1. 用作方法string[]的泛型类型参数reduce(感谢@depoulo 提及):
['a', 'b', 'c'].reduce<string[]>((accumulator, value) => accumulator.concat(value), []);
  1. 键入accumulatorstring[](并避免在上进行类型转换[]):
['a', 'b', 'c'].reduce((accumulator: string[], value) => accumulator.concat(value), []);

在 typescript playground 中使用此解决方案。

备注

  1. 如果可以的话,应该避免使用类型断言(有时称为类型转换),因为您正在采用一种类型并将其转换为其他类型。这可能会导致副作用,因为您手动控制将变量强制转换为另一种类型。

  2. This typescript error only occurs if the strictNullChecksoption is set totrue . 禁用该选项时,Typescript 错误会消失,但这可能不是您想要的。

  3. 我在这里引用了我使用 Typescript 收到的整个错误消息,3.9.2以便 Google 为正在搜索答案的人找到此线程(因为 Typescript 错误消息有时会因版本而异):

    No overload matches this call.
      Overload 1 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
     Argument of type 'string' is not assignable to parameter of type 'ConcatArray<never>'.
      Overload 2 of 2, '(...items: ConcatArray<never>[]): never[]', gave the following error.
     Argument of type 'string' is not assignable to parameter of type 'ConcatArray<never>'.(2769)
    
于 2020-06-23T14:54:44.727 回答
3

您应该使用泛型来解决这个问题。

['a', 'b', 'c'].reduce<string[]>((accumulator, value) => accumulator.concat(value), []);

这将设置初始空数组的类型,我认为这是最正确的解决方案。

于 2021-04-29T06:53:09.730 回答
0

即使将 tsconfig.json 文件更改为 "strict": false 并且只能避免使用以下内容破坏应用程序,上述方法均不适合我:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
于 2021-12-16T19:33:35.303 回答