代码胜过语言,因此:
['a', 'b', 'c'].reduce((accumulator, value) => accumulator.concat(value), []);
这段代码非常愚蠢,它只是返回一个复制的数组...
TypeScript 抱怨 concat 函数的参数:TS2345:类型“string”的参数不能赋值给类型“ConcatArray”的参数。
代码胜过语言,因此:
['a', 'b', 'c'].reduce((accumulator, value) => accumulator.concat(value), []);
这段代码非常愚蠢,它只是返回一个复制的数组...
TypeScript 抱怨 concat 函数的参数:TS2345:类型“string”的参数不能赋值给类型“ConcatArray”的参数。
我认为这是因为[]
的类型被推断为never[]
,这是一个必须为空的数组类型。您可以使用类型转换来解决这个问题:
['a', 'b', 'c'].reduce((accumulator, value) => accumulator.concat(value), [] as string[]);
通常这不会是什么大问题,因为 TypeScript 会根据你对它执行的操作来找出更好的类型来分配给一个空数组。然而,由于你的示例是“愚蠢的”,正如你所说的那样,TypeScript 无法做出任何推断,将类型保留为 never[]
。
一个更好的解决方案,它有两个变体避免了类型断言(又称类型转换):
string[]
作为reduce
方法的泛型类型参数(感谢@depoulo提到它):['a', 'b', 'c'].reduce<string[]>((accumulator, value) => accumulator.concat(value), []);
accumulator
的值作为string[]
类型输入(并避免在[]
上进行类型转换):['a', 'b', 'c'].reduce((accumulator: string[], value) => accumulator.concat(value), []);
在typescript playground中尝试这个解决方案。
注意事项:
如果可能的话,应该避免使用类型断言(有时称为类型转换),因为这会将一种类型转移到另一种类型。这可能会导致副作用,因为您手动控制将一个变量强制转换为另一种类型。
只有在设置strictNullChecks选项为true时才会出现此typescript错误。禁用该选项后,Typescript错误将消失,但这可能不是您想要的。
我引用了我在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)
['a', 'b', 'c'].reduce<string[]>((accumulator, value) => accumulator.concat(value), []);
- depoulo['a', 'b', 'c'].reduce<string[]>((accumulator, value) => accumulator.concat(value), []);
这将设置初始空数组的类型,我认为这是最正确的解决方案。
export const flatten = <T>(arr: T[]): T[] => arr.reduce((flat, toFlatten) =>
(flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten)), [] as T[]);
设置类型的另外两种方式,我比强制类型转换(即[] as string
)更喜欢的是:
<string[]>[]
Array<string>(0)
我在使用reduce函数时也遇到了同样的问题。之前的答案都可以,但如果你在将数组作为第二个参数传递给函数之前,先创建并输入数组,那么这也是非常简单明了的。
const alphabet = ['a', 'b', 'c']
let accumulatorArray: string[] = []
const reduction = alphabet.reduce((acc, curr) => {
acc.concat(curr)
}, accumulatorArray)
[]
的类型被推断为never[]
。如果这是真的,那么为什么const array = [];
推断出的类型是any[]
? - Patrick Robertsconst array = [];
这样做确实会产生一个any[]
数组。然而,我认为这是一个明确的例外,以避免混淆人们。如果你做类似于[].filter(a => true);
的事情,你会发现它推断出never[]
类型而不是any[]
类型。 - Matt H[]
被推断为某种“扩展any[]
”类型...... 显然在作为reduce()
中的累加器传递时不会发生这种情况。 ♀️ - jcalz