How do I restrict the type of React Children in TypeScript, using the newly added support in TypeScript 2.3?
Solution 1:
Edit 2: Turns out that this approach prevent the warning, but according to the comments TabProps
aren't properly checked.
You should try to set children of interface TabbedViewProps like so
interface TabbedViewProps { children?: React.ReactElement<TabProps>[] }
The idea here is not to tell your TabbedView
has an array of Tab
, but instead tell your TabbedView
he has an array of element
which takes specific props. In your case TabProps
.
Edit ( thx to Matei ):
interface TabbedViewProps {
children?: React.ReactElement<TabProps>[] | React.ReactElement<TabProps>
}
Solution 2:
As pointer out already, declaring TabbedView.children
as:
children: React.ReactElement<TabProps> | React.ReactElement<TabProps>[];
Will get rid of the error, but it won't be type-checking the children properly. That is, you will still be able to pass children other than TabProps
to TabbedView
without getting any error, so this would also be valid:
return (
<TabbedView>
<Tab name="Creatures">
<div>Creatures!</div>
</Tab>
<Tab name="Combat">
<div>Combat!</div>
</Tab>
<NotTabButValidToo />
</TabbedView>
);
What you could do instead is declare a prop, let's say tabs: TabProps[]
, to pass down the props you need to create those Tab
s, rather than their JSX, and render them inside TabbedView
:
interface TabbedViewProps {
children?: never;
tabs?: TabProps[];
}
...
const TabbedView: React.FC<TabbedViewProps > = ({ tabs }) => {
return (
...
{ tabs.map(tab => <Tab key={ ... } { ...tab } />) }
...
);
};
Solution 3:
I tried to assert the type. You can throw or just ignore.
interface TabbedViewProps {
children?: React.ReactElement<ITabProps> | React.ReactElement<ITabProps>[]
}
And in the component itself map the children and assert or ignore
{React.Children.map(props.children, (tab) => {
if(tab?.type != Tab) return;
console.log(tab?.type == Tab);
return tab;
})}