Машинописный текст: Запуск инструкции reduce с начальным значением?

#typescript

Вопрос:

Я пытаюсь написать довольно сложную инструкцию reduce, в которой я превращаю массив, а также массив массивов в массив объектов. Вот мои начальные массивы и тип, который я хотел бы получить:

 const fruits = ['apple', 'banana', 'pear', 'plum', 'grape'];
const fruitConsumers = [
  ['Jeremy, Claude', '', '', 'Helen, Benny, Sophie', ''],
  ['', 'Francis, Paul', '', 'Alice', 'Bob, Tracy', 'Lacey, Stacey'],
];

type FruitPersonMap = {
  apple: string[],
  banana: string[],
  pear: string[],
  plum: string[],
  grape: string[],
  people?: {
    name: string,
    fruit: string,
  }[]
}
 

По большей части это работает довольно хорошо, за исключением той части, где я хотел бы иметь в конце список всех людей и их плодов. По какой-то причине typescript это не нравится. Вот моя функция:

 const makeFruitPersonMap = (fruits: string[], consumers: string[][]): FruitPersonMap[] => {
  return consumers.map(consumerSet => {
    return consumerSet.reduce((acc, val: string, i: number) => {
      // the nth item in a consumer list will always correspond to the nth fruit
      const currentFruit = fruits[i];
      // turn the people into an array instead of a comma separated string
      const peopleList = val.split(',').map(name => name.trim());
      // turn the array of people into an array of objects with keys name, fruit
      const peopleWithFruit = peopleList.map(person => ({
        name: person,
        fruit: currentFruit,
      }))
      // add the current key to the accumulator and add the people objects onto the list.
      return {
        ...acc,
        [currentFruit]: peopleList,
        people: peopleWithFruit ? acc.people.concat(peopleWithFruit) : acc.people
      }
    }, { people: [] }) as FruitPersonMap
  })
};
 

Это приводит меня к ошибке: Conversion of type '{ people: never[]; }' to type 'FruitPersonMap' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first

Чего я не понимаю, так это почему people ключу задан тип never[] . Объединение вещей в people массив также создает для меня эту проблему, что для меня странно. Я также попытался добавить people ключ в функцию обратного вызова ( if (!acc.people) acc.people = [] ), но затем я получаю сообщение об ошибке о acc.people том, что он не существует {} . Я имею в виду, я согласен, что это плохой способ установить значение people ключа, но я проверил, существует ли он или нет. В чем дело!

Так что, я думаю, мой вопрос двоякий. Почему Typescript недоволен этим конкретным способом обработки reduce и есть ли способ настроить начальное значение reduce, которое не приводит к этой проблеме?

Ответ №1:

Я понял это примерно через 30 секунд после того, как набрал весь вопрос.

Новый тип:

 type PeopleList = {
  people: {
    name: string,
    fruit: string,
  }[]
}
 

Обновленная функция:

 const testFunc = (fruits: string[], consumers: string[][]) => {
  return consumers.map(consumerSet => {
    return consumerSet.reduce((acc, val: string, i: number) => {
      const currentFruit = fruits[i];
      const peopleList = val.split(',').map(name => name.trim());
      const peopleWithFruit = peopleList.map(person => ({
        name: person,
        fruit: currentFruit,
      }))
      return {
        ...acc,
        [currentFruit]: peopleList,
        people: peopleWithFruit ? acc.people.concat(peopleWithFruit) : acc.people
      }
    }, { people: [] } as PeopleList) as FruitPersonMap
  })
};
 

{ people: [] } as PeopleList Примечание. установка типа на начальное значение, которое перекрывается с FruitPersonMap, исправляет это.

Подумал, что оставлю этот вопрос открытым на случай, если кто-нибудь еще столкнется с этой проблемой и запутается, как это сделал я.