TypeScript и React - дочерний тип?

У меня есть очень простой функциональный компонент:

import * as React from 'react';

export interface AuxProps  { 
    children: React.ReactNode
 }


const aux = (props: AuxProps) => props.children;

export default aux;

И еще один компонент:

import * as React from "react";

export interface LayoutProps  { 
   children: React.ReactNode
}

const layout = (props: LayoutProps) => (
    <Aux>
        <div>Toolbar, SideDrawer, Backdrop</div>
        <main>
            {props.children}
        </main>
    <Aux/>
);

export default layout;

Я продолжаю получать следующую ошибку:

[TS] Тип элемента JSX 'ReactNode' не является функцией конструктора для элементов JSX.   Тип "undefined" не может быть назначен типу "ElementClass". [2605]

Как мне правильно это напечатать?

Ответы

Ответ 1

Чтобы использовать <Aux> в вашем JSX, это должна быть функция, которая возвращает ReactElement<any> | null ReactElement<any> | null Это определение функционального компонента.

Однако в настоящее время он определен как функция, которая возвращает React.ReactNode, который является гораздо более широким типом. Как написано в React:

type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;

Убедитесь, что нежелательные типы нейтрализованы, поместив возвращаемое значение во фрагмент React (<></>):

const aux: React.FC<AuxProps> = props =>
  <>{props.children}</>;

Ответ 2

Вот что сработало для меня:

interface Props {
  children: JSX.Element[] | JSX.Element
}

Ответ 3

Просто children: React.ReactNode

Ответ 4

Вы можете объявить свой компонент следующим образом:

const MyComponent: React.FunctionComponent = (props) => {
    return props.children;
}

Ответ 5

С сайта TypeScript: https://github.com/Microsoft/TypeScript/issues/6471

Рекомендуемая практика - писать тип реквизита как {children?: любой}

Это сработало для меня. Дочерний узел может быть много разных вещей, поэтому явная типизация может пропустить регистры.

Здесь есть более длинное обсуждение вопроса продолжения: https://github.com/Microsoft/TypeScript/issues/13618, но любой подход все еще работает.

Ответ 6

Общий способ найти любой тип - на примере. Прелесть машинописи в том, что у вас есть доступ ко всем типам, если у вас есть правильные файлы @types/.

Чтобы ответить на этот вопрос сам, я просто подумал о компонентах реакции, использующих опору children. Первое, что пришло в голову? Как насчет <div />?

Все, что вам нужно сделать, это открыть vscode и создать новый файл .tsx в реактивном проекте с @types/react.

import React from 'react';

export default () => (
  <div children={'test'} />
);

Наведите указатель мыши на опору children, чтобы увидеть тип. А что вы знаете - его тип ReactNode (нет необходимости в ReactNode[]).

enter image description here

Затем, если вы нажмете на определение типа, вы сразу перейдете к определению children, полученному из интерфейса DOMAttributes.

// node_modules/@types/react/index.d.ts
interface DOMAttributes<T> {
  children?: ReactNode;
  ...
}

Примечание: этот процесс должен использоваться для поиска любого неизвестного типа! Все они просто ждут, когда вы их найдете :)

Ответ 7

Реактивные компоненты должны иметь один узел-обертку или возвращать массив узлов.

Ваш компонент <Aux>...</Aux> имеет два узла div и main.

Попробуйте обернуть своих детей в элемент div в Aux.

import * as React from 'react';

export interface AuxProps  { 
  children: React.ReactNode
}

const aux = (props: AuxProps) => (<div>{props.children}</div>);

export default aux;