在 React 和 Typescript 中只允许特定组件作为子组件

IT技术 reactjs typescript typing
2021-05-01 07:11:09

我想只允许特定组件作为子组件。例如,假设我有一个 Menu 组件,它应该只包含MenuItem子项,如下所示:

<Menu>
  <MenuItem />
  <MenuItem />
</Menu>

因此,当我尝试将另一个组件作为子组件时,我希望 Typescript 在 IDE 中向我抛出一个错误。一些警告我只能MenuItem作为孩子使用的东西例如在这种情况下:

<Menu>
  <div>My item</div>
  <div>My item</div>
</Menu>

该线程几乎相似,但不包含 TypeScript 解决方案。我想知道是否可以使用 TypeScript 类型和接口解决这个问题。在我想象的世界中,它看起来像这样,但当然类型检查不起作用,因为子组件有一个Element类型:

type MenuItemType = typeof MenuItem;

interface IMenu {
  children: MenuItemType[];
}

const MenuItem: React.FunctionComponent<IMenuItem> = ({ props }) => {
  return (...)
}

const Menu: React.FunctionComponent<IMenu> = ({ props }) => {
  return (
    <nav>
      {props.children}
    </nav>
  )
}

const App: React.FunctionComponent<IApp> = ({ props }) => {
  return (
    <Menu>
      <MenuItem />
      <MenuItem />
    </Menu>
  )
}

有没有办法用 Typescript 实现这一点?喜欢使用仅与特定组件相关的内容来扩展 Element 类型?

或者什么是确保孩子是特定组件的实例的好方法?无需添加查看子组件 displayName 的条件。

1个回答

为此,您需要从子组件(最好也是父组件)中提取 props 接口并以这种方式使用它:

interface ParentProps {
    children: ReactElement<ChildrenProps> | Array<ReactElement<ChildrenProps>>;
}

所以在你的情况下,它看起来像这样:

interface IMenu {
  children: ReactElement<IMenuItem> | Array<ReactElement<IMenuItem>>;
}

const MenuItem: React.FunctionComponent<IMenuItem> = ({ props }) => {
  return (...)
}

const Menu: React.FunctionComponent<IMenu> = ({ props }) => {
  return (
    <nav>
      {props.children}
    </nav>
  )
}