TypeScript和React-子类型?

时间:2018-12-09 02:38:34

标签: reactjs typescript jsx typescript2.0

我有一个非常简单的功能组件,如下所示

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]

如何正确输入?

16 个答案:

答案 0 :(得分:23)

您可以使用ReactChildrenReactChild

import React, { ReactChildren, ReactChild } from 'react';

interface AuxProps {
  children: ReactChild | ReactChildren;
}

const Aux = ({ children }: AuxProps) => (<div>{children}</div>);

export default Aux;

答案 1 :(得分:17)

children: React.ReactNode

答案 2 :(得分:16)

您也可以使用React.PropsWithChildren<P>

type ComponentWithChildProps = React.PropsWithChildren<{example?: string}>;

答案 3 :(得分:8)

在TypeScript中,功能组件的返回类型限于JSXElement | null。这是当前的类型限制,即纯React allows more返回类型。

Minimal demonstration snippet

您可以使用类型断言或片段作为解决方法:

const Aux = (props: AuxProps) => <>props.children</>; 
const Aux2 = (props: AuxProps) => props.children as ReactElement; 

ReactNode

如果目标是为children: React.ReactNode提供强类型,则

Aux可能不是最佳选择。

几乎所有内容都可以分配给当前的ReactNode类型,这等效于{} | undefined | null。对于您的案件,更安全的类型可能是:

interface AuxProps {
  children: ReactElement | ReactElement[]
}

示例:

鉴于Aux需要像children那样的React元素,我们无意中添加了一个string。与above solution相比,ReactNode会出错-看一下链接的游乐场。

类型为children的非JSX道具也很有用,例如Render Prop回调。

答案 4 :(得分:5)

为了在您的JSX中使用XElement,它必须是一个返回<Aux>的函数。这就是功能组件的定义。

但是,当前定义为返回ReactElement<any> | null的函数,这是一个更广泛的类型。正如React输入所说的那样:

React.ReactNode

通过将返回的值包装到React Fragment(type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined; )中,确保不需要的类型被中和:

<></>

答案 5 :(得分:5)

这对我有用:

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

答案 6 :(得分:5)

我正在使用以下内容

type Props = { children: React.ReactNode };

const MyComponent: React.FC<Props> = ({children}) => {
  return (
    <div>
      { children }
    </div>
  );

export default MyComponent;

答案 7 :(得分:4)

您可以这样声明组件:

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

答案 8 :(得分:4)

这一直对我有用:

type Props = {
  children: JSX.Element;
};

答案 9 :(得分:3)

这些答案似乎已过时-React现在具有内置类型PropsWithChildren<{}>。它的定义类似于此页面上的一些正确答案:

type PropsWithChildren<P> = P & { children?: ReactNode };

答案 10 :(得分:3)

React Node是以下类型之一:

  • Boolean(将被忽略)
  • nullundefined(将被忽略)
  • Number
  • String
  • 一个React elementJSX的结果)
  • 上述任何一项的数组,可能是嵌套的

答案 11 :(得分:2)

作为一种包含子代的类型,我正在使用:

type ChildrenContainer = Pick<JSX.IntrinsicElements["div"], "children">

此子容器类型具有足够的通用性,可以支持所有不同的情况,并且与ReactJS API保持一致。

因此,对于您的示例,它类似于:

const layout = ({ children }: ChildrenContainer) => (
    <Aux>
        <div>Toolbar, SideDrawer, Backdrop</div>
        <main>
            {children}
        </main>
    <Aux/>
)

答案 12 :(得分:2)

您也可以使用 JSX.ElementChildrenAttribute

export default function Layout({children}: JSX.ElementChildrenAttribute) {
    return <div>
        {children}
    </div>
}

答案 13 :(得分:0)

从TypeScript网站:https://github.com/Microsoft/TypeScript/issues/6471

  

建议的做法是将props类型写为{children ?:   任何}

对我有用。子节点可以有很多不同的东西,因此显式键入可能会遗漏大小写。

这里有一个有关后续问题的较长讨论:https://github.com/Microsoft/TypeScript/issues/13618,但是任何方法仍然有效。

答案 14 :(得分:0)

通用查找任何类型的方法是示例。打字稿的妙处在于,只要您拥有正确的@types/文件,您就可以访问所有类型。

我自己想回答这个问题,我只是想到了具有children道具的组件react用法。我想到的第一件事是? <div />怎么样?

您需要做的就是打开vscode并使用.tsx在react项目中创建一个新的@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;
  ...
}
  

注意:此过程应用于查找任何未知类型!他们都在那里等着你找到他们:)

答案 15 :(得分:-1)

反应组件应具有单个包装器节点或返回节点数组。

您的<Aux>...</Aux>组件有两个节点divmain

尝试将孩子包装在div组件中的Aux中。

import * as React from 'react';

export interface AuxProps  { 
  children: React.ReactNode
}

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

export default aux;