TSX: интерфейс вложенного рекурсивного массива объектов

Я не могу заставить свой машинописный интерфейс работать с реагирующим компонентом tsx. У меня есть все элементы внутри массива объектов с возможными подэлементами.

Я пробовал много разных интерфейсов, но всегда заканчивал какой-то ошибкой, в настоящее время кажется, что только функция карты не работает с интерфейсом. (Я нуб и вчера впервые начал использовать машинопись :P)

введите здесь описание изображения

interface NavListItem {
  ID: string;
  title: string;
  path_url: string;
  child_items?: NavListProps;
}

interface NavListProps {
  items: { [index: number]: NavListItem };
}

const NavList: React.FC<NavListProps> = ({ items }) => {
  return items.map(item => (
    <li key={item.ID}>
      <Link to={item.path_url}>{item.title}</Link>
      {item.child_items ? (
        <ul>{<NavList items={item.child_items} />}</ul>
      ) : null}
    </li>
  ));
};

Моя цель - чтобы не было ошибок и работал компонент. Я ценю всю помощь!


person josias    schedule 13.07.2019    source источник
comment
Вы определили items как объект.   -  person lux    schedule 13.07.2019


Ответы (1)


Если items должен быть массивом, то правильный интерфейс для реквизита таков:

interface NavListProps {
  items: NavListItem[];
}

Как вы определили, items — это объект с произвольными парами ключ-значение, единственным ограничением которого является то, что ключи должны быть числами, а значения должны быть NavListItems. Это не означает, что это массив, поэтому typescript указывает, что этот тип не имеет метода карты.

Пара дополнительных вопросов (как обсуждалось в комментариях):

1) Когда вы рекурсивно визуализируете NavList, вы передаете item.child_items, но это определяется как один NavListProps, тогда как вместо этого он должен быть NavListItem[]:

interface NavListItem {
  ID: string;
  title: string;
  path_url: string;
  child_items?: NavListItem[];
}

2) Ваш компонент возвращает только массив, но вместо этого его следует обернуть фрагментом:

const NavList: React.FC<NavListProps> = ({ items }) => {
  return (
    <React.Fragment>
      {items.map(item => (
        <li key={item.ID}>
          <Link to={item.path_url}>{item.title}</Link>
          {item.child_items ? (
            <ul>{<NavList items={item.child_items} />}</ul>
          ) : null}
        </li>
      }
    </React.Fragment>
  ));
};

P.S.: если ваша сборка настроена правильно, можно сделать <></> сокращением для <React.Fragment></React.Fragment>

person Nicholas Tower    schedule 13.07.2019
comment
Вот так я получаю сообщение об ошибке типа React.FC, что-то вроде: type /thefunction/ is not assignable to type FunctionComponent<NavListProps>. Type Element[] is missing the following properties from type ReacElement any type, props, key... - person josias; 13.07.2019
comment
О, я думаю, ему не нравится, что вы возвращаете массив. Оберните его фрагментом, как в return <React.Fragment>{items.map(item => /* etc */)}</React.Fragment> - person Nicholas Tower; 13.07.2019
comment
Кажется, это сработало, только теперь при вызове самого себя для реквизита (внутри ul) возникает ошибка, говорящая Type 'NavListProps' is missing the following properties from type NavListItem[]: length, pop, push, concat and 28 more ... Я пытаюсь создать рекурсивный список - person josias; 13.07.2019
comment
Ваш интерфейс для NavListItem определяет item.child_items как одиночный NavListItem, а не их массив. Если это на самом деле массив, измените интерфейс. Если это действительно один, то оберните его в массив, прежде чем передавать его компоненту NavList (или, я полагаю, перепишите NavList, чтобы он принимал либо массив, либо один, но это было бы больше работы) - person Nicholas Tower; 13.07.2019
comment
Хорошо, большое спасибо, я изменил строку с child_items?: NavListProps; на child_items?: NavListItem[];, и теперь это работает :) - person josias; 13.07.2019
comment
Возможно, добавьте в свой ответ часть Fragment и child_items, чтобы я мог принять это ???????? - person josias; 13.07.2019