TypeScript 和 React - 儿童类型?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53688899/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 08:00:33  来源:igfitidea点击:

TypeScript and React - children type?

reactjstypescriptjsxtypescript2.0

提问by Asool

I have a very simple functional component as follows:

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

import * as React from 'react';

export interface AuxProps  { 
    children: React.ReactNode
 }


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

export default aux;

And another component:

另一个组件:

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;

I keep on getting the following error:

我不断收到以下错误:

[ts] JSX element type 'ReactNode' is not a constructor function for JSX elements. Type 'undefined' is not assignable to type 'ElementClass'. [2605]

[ts] JSX 元素类型“ReactNode”不是 JSX 元素的构造函数。类型 'undefined' 不能分配给类型 'ElementClass'。[2605]

How do I type this correctly?

我如何正确输入?

回答by Ridd

Just children: React.ReactNode

只是 children: React.ReactNode

回答by Karol Majewski

In order to use <Aux>in your JSX, it needs to be a function that returns ReactElement<any> | null. That's the definition of a function component.

为了<Aux>在您的 JSX 中使用,它需要是一个返回ReactElement<any> | null. 这就是功能组件的定义。

However, it's currently defined as a function that returns React.ReactNode, which is a much wider type. As React typings say:

但是,它目前被定义为一个返回 的函数React.ReactNode,这是一个更广泛的类型。正如 React 类型所说:

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

Make sure the unwanted types are neutralized by wrapping the returned value into React Fragment (<></>):

通过将返回值包装到 React Fragment ( <></>)中,确保消除不需要的类型:

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

回答by sunknudsen

This is what worked for me:

这对我有用:

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

EditI would recommend using children: React.ReactNodeinstead now.

编辑我建议children: React.ReactNode现在使用。

回答by jsina

you can declare your component like this:

你可以像这样声明你的组件:

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

回答by Mike S

From the TypeScript site: https://github.com/Microsoft/TypeScript/issues/6471

来自 TypeScript 站点:https: //github.com/Microsoft/TypeScript/issues/6471

The recommended practice is to write the props type as {children?: any}

推荐的做法是将 props 类型写为 {children?: any}

That worked for me. The child node can be many different things, so explicit typing can miss cases.

那对我有用。子节点可以是许多不同的东西,因此显式类型可能会遗漏案例。

There's a longer discussion on the followup issue here: https://github.com/Microsoft/TypeScript/issues/13618, but the any approach still works.

这里有关于后续问题的更长讨论:https: //github.com/Microsoft/TypeScript/issues/13618,但 any 方法仍然有效。

回答by ford04

children: React.ReactNodeis a bad idea, if you want childrento have a stronger type.

children: React.ReactNode是个坏主意,如果你想要children一个更强的类型。

You can assign almost anythingto ReactNode, it behaves like the type {} | undefined | null. Given you want an array of ReactElementchildren for Aux, a better idea is to use:

您几乎可以将任何内容分配给ReactNode,它的行为类似于 type {} | undefined | null。鉴于您想要一组ReactElement儿童 for Aux,一个更好的主意是使用:

interface AuxProps {
    children: React.ReactElement[] // or JSX.Element[]
}

This type only allows an arrayof children and e.g. prevents stringas child- ReactNodewould just ignore it. Typed childrenare also useful, if anything other than an JSX expression is passed, like a function to enable Render Props.

这种类型只允许一个孩子的数组,例如防止string作为孩子-ReactNode忽略它children如果传递 JSX 表达式以外的任何内容,则键入也很有用,例如启用Render Props的函数。

Current TS limitationis that the return type in function components is limited to JSXElement | null(ReactJS allows more). In edge cases you can either use a fragment or cast (see also Karol Majewski's answer):

当前的TS 限制是函数组件中的返回类型仅限于JSXElement | null(ReactJS允许更多)。在极端情况下,您可以使用片段或演员表(另请参阅 Karol Majewski 的回答):

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

回答by Nickofthyme

The generalway to find any type is by example. The beauty of typescript is that you have access to alltypes, so long as you have the correct @types/files.

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

To answer this myself I just thought of a component react uses that has the childrenprop. The first thing that came to mind? How about a <div />?

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

All you need to do is open vscodeand create a new .tsxfile in a react project with @types/react.

您需要做的就是打开vscode.tsx在 react 项目中创建一个新文件@types/react

import React from 'react';

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

Hovering over the childrenprop shows you the type. And what do you know -- Its type is ReactNode(no need for ReactNode[]).

将鼠标悬停在children道具上会显示类型。你知道什么——它的类型是ReactNode(不需要ReactNode[])。

enter image description here

在此处输入图片说明

Then if you click into the type definition it brings you straight to the definition of childrencoming from DOMAttributesinterface.

然后,如果您单击类型定义,它会直接将您带到children来自DOMAttributes接口的定义。

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

Note: This process should be used to find any unknown type! All of them are there just waiting for you to find them :)

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

回答by Denis

As a type that contains children, I'm using:

作为包含子项的类型,我正在使用:

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

This children container type is generic enough to support all the different cases and also aligned with the ReactJS API.

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

So, for your example it would be something like:

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

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

回答by Tim Iles

These answers appear to be outdated - React now has a built in type PropsWithChildren<{}>. It is defined similarly to some of the correct answers on this page:

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

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

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

回答by Dinesh Pandiyan

React components should have a single wrapper node or return an array of nodes.

React 组件应该有一个单一的包装节点或返回一个节点数组。

Your <Aux>...</Aux>component has two nodes divand main.

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

Try to wrap your children in a divin Auxcomponent.

尝试将您的孩子包裹在一个divinAux组件中。

import * as React from 'react';

export interface AuxProps  { 
  children: React.ReactNode
}

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

export default aux;