У меня ниже
const foo = (
fields: {
[key: string]: string,
}
) => {
const { one, two } = Object.values(fields).reduce(
(acc, field) => {
if (isOne(field)) {
return { ...acc, two: [...acc.two, field] }
}
return { ...acc, one: [...acc.one, field] }
},
{ one: [], two: [] }
)
// ...
}
Но я все время получаю сообщение об ошибке
Argument of type '(acc: { one: never[]; two: never[]; }
1 ответ
Если вы присваиваете переменной объект, содержащий пустые литералы массива, компилятор будет склонять к выводу, что эти массивы имеют тип never[]
, что является довольно бесполезным типом:
const init = { one: [], two: [] };
/* const init: {
one: never[];
two: never[];
} */
init.one.push("whoops"); // error!
Вероятно, это ограничение TypeScript в дизайне согласно microsoft / TypeScript # 29398. Вы можете ожидать, что компилятор отложит присвоение типа пустому литералу массива до тех пор, пока у него не появится больше контекста для того, какими будут типы элементов, но такой отложенный вывод часто имеет другие побочные эффекты.
На данный момент я бы посоветовал, если компилятор определит тип, который вам не нужен для определенного значения, вы должны аннотировать или вместо этого подтвердите тип этого значения:
const init2: { one: string[], two: string[] } = { one: [], two: [] };
init2.one.push("okay"); // okay
Для кода reduce()
, который у вас здесь, компилятор делает вывод, что аккумулятор имеет тип {one: never[], two: never[]}
. Он не может согласовать это с типом возвращаемого значения обратного вызова редуктора (что-то вроде {one: string[], two: never[]} | {one: never[], two: string[]}
) и поэтому отказывается от этой сигнатуры вызова. Поскольку reduce()
является перегруженной функцией и компилятор не может сопоставить ваш вызов ни одной из сигнатур вызовов, вы получите сообщение об ошибке перегруженных функций.
Опять же, правильнее всего здесь сказать компилятору, что начальное значение вашего аккумулятора имеет тип {one: string[], two: string[]}
. Самый простой способ сделать это - явно указать общий параметр типа в вызове reduce()
:
const { one, two } = Object.values(fields).
reduce<{ one: string[], two: string[] }>( // <-- specify here
(acc, field) => {
if (isOne(field)) {
return { ...acc, two: [...acc.two, field] }
}
return { ...acc, one: [...acc.one, field] }
},
{ one: [], two: [] }
)
Теперь ошибки нет: если аккумулятор набирается как {one: string[], two: string[]}
, вызов reduce()
работает, потому что обратный вызов, как предполагается, возвращает значение того же типа, что и требуется.
Хорошо, надеюсь, что это поможет; удачи!
Детская площадка ссылка на код
Похожие вопросы
Новые вопросы
typescript
TypeScript - это типизированный надмножество JavaScript, которое компилируется в простой JavaScript. Он добавляет в JavaScript дополнительные типы, классы, интерфейсы и модули. Этот тег предназначен для вопросов, относящихся к TypeScript. Он не используется для ответов на общие вопросы по JavaScript.