React + TypeScript 只允许特定类型的孩子

JSE*_*eny 14 typescript reactjs

我在尝试只允许将特定子项传递给组件时遇到了麻烦。

这是我的组件,HeaderLink

import { SFC, ReactElement } from "react";

import "./Header.scss";

export interface IHeaderLinkProps {
  url: string;
  label: string;
}

const HeaderLink: SFC<IHeaderLinkProps> = ({ url, label }): ReactElement => (
  <li className="nav-item">
    <a href={url}>{label}</a>
  </li>
);

export default HeaderLink;
Run Code Online (Sandbox Code Playgroud)

和标题

import { SFC, ReactElement } from "react";
import { IHeaderLinkProps } from "./HeaderLink";

import "./Header.scss";

interface IHeaderProps {
  children: ReactElement<IHeaderLinkProps> | ReactElement<IHeaderLinkProps>[];
}

const Header: SFC<IHeaderProps> = ({ children }): ReactElement => {
  return (
    <header className="header">
      <div className="container">
        <div className="row">
          <div className="col">
            <img
              className="header__logo"
              src={"/logo.png"}
              alt="monqrime-logo"
            />

            <ul className="header__nav">{children}</ul>
          </div>
        </div>
      </div>
    </header>
  );
};
Run Code Online (Sandbox Code Playgroud)

所以问题是我只想允许 HeaderLink 组件作为子级传递给 Header,但我当前的解决方案仍然允许我将所有内容作为子级。

Dan*_*ger 9

我可能会声明IHeaderProps.children为:

children: React.ReactElement<IHeaderProps> | React.ReactElement<IHeaderProps>[];
Run Code Online (Sandbox Code Playgroud)

考虑同时拥有一个孩子和多个孩子的可能性。

无论如何,你想要的都是不可能的。看:

你可以做的是声明一个道具,比方说links?: IHeaderLinkProps[],传递创建这些HeaderLinks所需的道具,而不是它们的 JSX,并将它们呈现在里面Header

interface IHeaderProps {
  children?: never;
  links?: IHeaderLinkProps[];
}

...

const Header: React.FC<IHeaderProps> = ({ links }) => {
  return (
    ...

    <ul className="header__nav">
      { links.map(link => <HeaderLink key={ link.url } { ...link } />) }
    </ul>

    ...
  );
};
Run Code Online (Sandbox Code Playgroud)

  • 我感谢您的帮助@Danziger,但不幸的是,您的第一个解决方案对我不起作用,而是抛出“类型'Element []'不可分配给类型'ComponentType &lt;IHeaderLinkProps&gt; []'”。类型“Element”不可分配给类型“ComponentType&lt;IHeaderLinkProps&gt;”。`您的第二个解决方案肯定会起作用,这是我的第一个实现,但我只是想让它看起来更奇特:D (2认同)