Подтвердить что ты не робот

Как ограничить тип React Children в TypeScript, используя недавно добавленную поддержку в TypeScript 2,3?

Я пытаюсь использовать недавно добавленную поддержку для ввода детей в компиляторе TypeScript и @type/react, но борется. Я использую TypeScript версию 2.3.4.

Скажем, у меня такой код:

interface TabbedViewProps {children?: Tab[]}
export class TabbedView extends React.Component<TabbedViewProps, undefined> {

  render(): JSX.Element {
    return <div>TabbedView</div>;
  }
}

interface TabProps {name: string}
export class Tab extends React.Component<TabProps, undefined> {
  render(): JSX.Element {
    return <div>Tab</div>
  }
}

Когда я пытаюсь использовать эти компоненты следующим образом:

return <TabbedView>
  <Tab name="Creatures">
    <div>Creatures!</div>
  </Tab>
  <Tab name="Combat">
    <div>Combat!</div>
  </Tab>
</TabbedView>;

Я получаю сообщение об ошибке следующим образом:

ERROR in ./src/typescript/PlayerView.tsx
(27,12): error TS2322: Type '{ children: Element[]; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<TabbedView> & Readonly<{ children?: ReactNode; }> ...'.
  Type '{ children: Element[]; }' is not assignable to type 'Readonly<TabbedViewProps>'.
    Types of property 'children' are incompatible.
      Type 'Element[]' is not assignable to type 'Tab[] | undefined'.
        Type 'Element[]' is not assignable to type 'Tab[]'.
          Type 'Element' is not assignable to type 'Tab'.
            Property 'render' is missing in type 'Element'.

Кажется, вывод типа детей как только Element[] вместо Tab[], хотя это единственный тип детей, которые я использую.

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

4b9b3361

Ответ 1

Вы должны попытаться установить дочерние элементы интерфейса TabbedViewProps следующим образом

interface TabbedViewProps { children?: React.ReactElement<TabProps>[] }

Идея здесь не в том, чтобы сказать, что ваш TabbedView имеет массив Tab, а вместо этого сказать вашему TabbedView у него есть массив element который принимает определенные реквизиты. В вашем случае TabProps.

Изменить (спасибо Матей):

interface TabbedViewProps {
    children?: React.ReactElement<TabProps>[] | React.ReactElement<TabProps>
}

Редактировать 2: Оказывается, что этот подход предотвращает предупреждение, но согласно комментариям TabProps не проверены должным образом.

Ответ 2

Тип, возвращаемый в методе отображения вкладки, - это JSX.Element. Это и является причиной вашей проблемы. TabbedView ожидает массив дочерних элементов с типом Tab. Я не уверен, что вы можете указать определенный компонент как тип детей. Это может быть строка или JSX.Element. Вы можете показать файл определения для Tab?

Посмотрите https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react/index.d.ts, чтобы увидеть, как выглядит интерфейс JSX.Element.