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.ElementType
s 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 Submenu
s and/or MenuItem
s?