reactjs - React + TypeScript permit doar copii de un anumit tip


Am întâmpinat o problemă încercând să permit trecerea doar a unor copii specifici către un component.

Aici sunt componentele mele, 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;

și antet

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>
  );
};

Deci problema este că vreau să permit doar componentelor HeaderLink să fie transmise ca copii către Header, dar soluția mea actuală încă îmi permite să pun orice ca și copii.

Răspuns #1

Probabil aș declara IHeaderProps.children ca:

children: React.ReactElement<IHeaderProps> | React.ReactElement<IHeaderProps>[];

Pentru a ține cont de posibilitatea de a avea atât un singur copil, cât și mai mulți copii.

În orice caz, ceea ce vrei nu este posibil. Vezi:

  • Cum pot restricționa tipul copiilor React în TypeScript, folosind suportul adăugat recent în TypeScript 2.3?

  • Verificarea tipului pentru copii în componenta React cu TypeScript

Ceea ce ai putea face în schimb este să declari o proprietate, să zicem links?: IHeaderLinkProps[], pentru a transmite proprietățile de care ai nevoie pentru a crea acele HeaderLink-uri, în loc de JSX-ul lor, și să le redai în interiorul 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>

    ...
  );
};