1

I am trying to type a react component such that it only accepts certain types of children. The component is called ItemGroup, and it should only accept components (or arrays of components) called Submenu or MenuItem. For now, let's say it can only accept a single Submenu as a child:

I define the Submenu component and props:

interface SubmenuProps {
  popupId: string;
}

export const Submenu: React.FC<SubmenuProps> = ({ popupId }: SubmenuProps) => {
  return <div>some stuff</div>;
};

And now I define the ItemGroup, and type its children to allow only React.ElementTypes of SubmenuProps, or an array thereof:

interface ItemGroupProps {
  title: string;
  children: React.ElementType<SubmenuProps> | React.ElementType<SubmenuProps>[];
}

export const ItemGroup: React.FC<ItemGroupProps> = (props: ItemGroupProps) => {
  const { title, children } = props;
  return (
    <>
      <div>{title}</div>
      {children}
    </>
  );
};

I try to actually use it as such:

export default function App() {
  return (
    <ItemGroup title="something">
      <Submenu popupId="123" />
    </ItemGroup>
  );
}

On the use of <Submenu />, I get an error:

Type 'Element' is not assignable to type 'FunctionComponent<SubmenuProps> | ComponentClass<SubmenuProps, any> | ElementType<SubmenuProps>[] | ... 20 more ... | (ElementType<...>[] & ReactPortal)'.
  Type 'Element' is not assignable to type 'ElementType<SubmenuProps>[] & ReactPortal'.
    Type 'Element' is missing the following properties from type 'ElementType<SubmenuProps>[]': length, pop, push, concat, and 25 more.ts(2322)
App.tsx(14, 3): The expected type comes from property 'children' which is declared here on type 'IntrinsicAttributes & ItemGroupProps & { children?: ReactNode; }'

Codesandbox demonstrating the problem

I have done this type of thing before, i.e. forcing certain types of children, by using a children: React.Elementype<ChildProps> in the props interface for the parent. Why am I getting an error here. How can I type the ItemGroup's children prop to only allow Submenus and/or MenuItems?

Seth Lutske
  • 9,154
  • 5
  • 29
  • 78
  • 1
    You should be using `React.ReactElement` instead of `React.ElementType`, but it doesn't successfully limit the children based on props (see the answers in the question linked as duplicate). – Ryan Cogswell Jul 21 '21 at 20:56

0 Answers0