Почему TypeScript выводит тип 'never' при уменьшении массива с помощью concat?
Код говорит лучше языка, поэтому:
['a', 'b', 'c'].reduce((accumulator, value) => accumulator.concat(value), []);
Код очень глупый и возвращает скопированный массив...
TS жалуется на аргумент concat: TS2345: Аргумент типа 'string' не может быть назначен параметру типа 'ConcatArray'.
7 ответов
Я считаю, что это потому, что тип для []
предполагается, что never[]
, который является типом для массива, который ДОЛЖЕН быть пустым. Вы можете использовать приведение типа для решения этой проблемы:
['a', 'b', 'c'].reduce((accumulator, value) => accumulator.concat(value), [] as string[]);
Обычно это не будет большой проблемой, поскольку TypeScript хорошо справляется с задачей определения лучшего типа для назначения пустому массиву на основе того, что вы с ним делаете. Тем не менее, поскольку ваш пример "глупый", как вы говорите, TypeScript не может делать какие-либо выводы и оставляет тип как never[]
,
Лучшее решение, которое позволяет избежать приведения типа:
Введите accumulator
ценность как string[]
(и избегайте приведения типа к[]
):
['a', 'b', 'c'].reduce((accumulator: string[], value) => accumulator.concat(value), []);
Поиграйте с этим решением на игровой площадке машинописного текста.
Примечания:
Приведения типов следует по возможности избегать, потому что вы берете один тип и переносите его на другой. Это может вызвать побочные эффекты, поскольку вы вручную берете на себя управление преобразованием переменной в другой тип.
Эта машинописная ошибка возникает, только если
strictNullChecks
опция установлена наtrue
. Ошибка 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), []);
Это установит тип исходного пустого массива, что, на мой взгляд, является наиболее правильным решением.
Вы можете использовать универсальный тип, чтобы избежать этой ошибки.
Проверьте мой пример функции flatten:
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)
У меня была такая же проблема с функцией сокращения. Предыдущие ответы хороши, но это также довольно просто, если вы просто создадите и напечатаете массив, прежде чем передать его функции в качестве второго параметра.
const alphabet = ['a', 'b', 'c']
let accumulatorArray: string[] = []
const reduction = alphabet.reduce((acc, curr) => {
acc.concat(curr)
}, accumulatorArray)
ничего из вышеперечисленного не сработало для меня, даже с изменением файла tsconfig.json на «strict»: false, и мне удалось избежать поломки приложения только со следующим:
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore