【问题标题】:React + TypeScript only allow children of specific typeReact + TypeScript 只允许特定类型的孩子
【发布时间】:2020-04-10 08:56:32
【问题描述】:

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

这是我的组件,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;

和标题

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

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

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    我正在这样做(基于 Danziger 的回答):

    type MaybeArray<T> = T[] | T
    export type ChildrenOfType<T> = MaybeArray<ReactElement<ComponentPropsWithoutRef<T>>>
    

    用法:

    interface SelectBoxProps extends Pick<React.ComponentPropsWithoutRef<'select'>, 'id' | 'value' | 'onChange' | 'disabled' | 'readOnly' | 'onFocus' | 'onBlur' | 'required' | 'defaultValue' | 'style'> {
        children?: ChildrenOfType<'option'>
    }
    

    我不知道它是否真的有任何作用——我的 IDE 不会在我向其中抛出 &lt;div&gt; 时抱怨,但至少它可以用作人工文档。

    【讨论】:

      【解决方案2】:

      我可能会将IHeaderProps.children 声明为:

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

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

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

      你可以做的是声明一个道具,比如说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>
      
          ...
        );
      };
      

      【讨论】:

      • 感谢您的帮助 @Danziger,但不幸的是,您的第一个解决方案对我不起作用,而是抛出 Type 'Element[]' is not assignable to type 'ComponentType&lt;IHeaderLinkProps&gt;[]'. Type 'Element' is not assignable to type 'ComponentType&lt;IHeaderLinkProps&gt;'. 您的第二个解决方案肯定会起作用,这是我的第一个实现,但我只是想要让它看起来更花哨:D
      • @JSEvgeny 我的错,应该是React.ReactElement,而不是React.ComponentType。无论如何,即使这看起来是正确的方法,它也不起作用(如其他 2 个问题所示),但它不会显示错误。您最好的选择是使配置驱动,这就是我在答案第二部分中的建议。
      • 是的,我想出了我遇到的问题,然后才发现它不适用于您发送的答案:(我仍然希望有新的可能解决方案出现,但如果没有做任何我都会去的基础知识并接受你的回答
      • 我将把 HeaderLinkProps 类型的对象数组作为属性传递,因为没有更多的建议了 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-24
      • 2015-02-06
      • 2022-01-23
      • 2019-08-06
      • 2021-11-03
      • 1970-01-01
      相关资源
      最近更新 更多