反应儿童的正确打字稿类型是什么?

What is the correct typescript type for react children?

我正在尝试为映射子项的组件正确键入道具:

type Props = {
    children: any
}

const MyComponent: FunctionComponent<Props> = () => (React.Children.map(children, someMapingFunction);

我一直在使用 JSX.Element,但感觉不太对。

查看 DefinitelyTyped 下的代码,children 似乎输入为 ReactNode

示例:

type Props = {
    children: ReactNode
}

const MyComponent: FunctionComponent<Props> = () => (React.Children.map(children, someMapingFunction);

注意ReactNode类型可以在React命名空间中找到:

import React from 'react';

let someNode: React.ReactNode;

实际上,如果您使用 React.FunctionComponent,则不必指定 children

例如下面的代码编译没有错误:

const MyComponent: React.FC<{}> = props => {
  return props.children
}

不是ReactNode而是ReactElement<any, any> | null

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/e90f1299270f6d602fa1af074fb5b3b088c53c09/types/react/index.d.ts#L511

    interface FunctionComponent<P = {}> {
        (props: P, context?: any): ReactElement<any, any> | null;
        propTypes?: WeakValidationMap<P> | undefined;
        contextTypes?: ValidationMap<any> | undefined;
        defaultProps?: Partial<P> | undefined;
        displayName?: string | undefined;
    }

children 和其他道具一样,可以是任何类型。唯一的特殊之处在于子 JSX 元素会自动映射到 children 属性。

因此,虽然它通常被声明为 children?: React.ReactNode,但您可以将其声明为 render prop,甚至像这样的自定义类型:

interface INameProps {
    children: {
        fistName: string,
        lastName: string
    }
}

const Name: React.FC<INameProps> = ({children}) => {
    return <div>{children.fistName} {children.lastName}</div>;
}

然后你可以像这样使用它:

<Name>
    {
        {
            fistName: "John",
            lastName: "Smith"
        }
    }
</Name>

与以下相同:

<Name
    children={
        {
            fistName: "John",
            lastName: "Smith"
        }
    }
/>