Рекурсивное отображение реквизитов для React детей в Typescript - PullRequest
2 голосов
/ 11 июня 2019

Я создаю слой привязок React, чтобы создать простое соединение между библиотекой пользовательского интерфейса и SDK.

Для этого я рекурсивно сопоставляю свойства родительского компонента каждому дочернему элементу в узле,например:

<Bookies.UserBookieList>
  <BookieBarItem />
</Bookies.UserBookieList>

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

Функция рекурсивной карты выглядит следующим образом:

import React, { PropsWithChildren, ReactElement } from 'react';

export default function recursivelyMapChildren<AddedProperties>(
  children: ReactElement<PropsWithChildren<AddedProperties>>[],
  addedProperties: AddedProperties
): any {
  return React.Children.map(children, child => {
    if (!child.props.children) {
      return React.cloneElement<PropsWithChildren<AddedProperties>>(child, addedProperties);
    }
    if (React.isValidElement(child)) {
      return React.cloneElement<PropsWithChildren<AddedProperties>>(
        child,
        addedProperties,
        ...recursivelyMapChildren<PropsWithChildren<AddedProperties>>(
          child.props.children as ReactElement<PropsWithChildren<AddedProperties>>[],
          addedProperties
        )
      );
    }
    return child;
  });
}

И вот как Bookies.UserBookieList использует его:

interface UserBookieListChildProps {
  code: string;
  name: string;
  bookiePosition: number;
  index: number;
  isActive: boolean;
  loggedIn: boolean;
  onBookieSelect: (bookie: any, bookiePosition: number) => void;
}

class UserBookieList extends PureComponent<UserBookieListProps> {
  public handleBookieSelect = (bookie: any, bookiePosition: number) => {
    this.props.setClientBookie(bookie);

    trackEvent(TRACKING_EVENTS.USER_BOOKIE_SELECT, {
      betBookie: bookie,
      clickPosition: bookiePosition
    });
  };

  public render(): ReactElement<UserBookieListChildProps>[] {
    const { bookie: { code }, children, userBookies } = this.props;
    return userBookies.map((bookie: any, index: number) =>
      recursiveMap<UserBookieListChildProps>(children, {
        ...bookie,
        key: index,
        bookiePosition: index + 1,
        index,
        isActive: bookie.code === code,
        onBookieSelect: this.handleBookieSelect
      }).shift()
    );
  }
}

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

TS2740: Type '{}' is missing the following properties from type 'Readonly<BookieBarItemProps>': code, index, isActive, loggedIn, and 2 more.

Я подумал, что предоставив UserBookieListChildProps интерфейс для recursiveMap и передав его в React.cloneElement, как это будет сделано при наборе реквизитов элементатрюк, но это не так ...

Любая помощь будет высоко ценится!

...