I want to make a Tabs component that infers the possible values of the active prop based on what its children have as name props. This is how I tried to do it:
import React from 'react'
interface TabProps<N extends string> {
name: N
}
function Tab<N extends string>(props: TabProps<N>) {
return null
}
type TabsType<N extends string = string> =
| React.FunctionComponentElement<TabProps<N>>
| React.FunctionComponentElement<TabProps<N>>[]
interface TabsProps<Tabs extends TabsType> {
children: Tabs
active: Tabs extends TabsType<infer N> ? N : unknown
}
export function Tabs<Tabs extends TabsType>(props: TabsProps<Tabs>) {
return null
}
const test = (
{/* I want active to be inferred as type 'bla' | 'hey' */}
<Tabs active="blabla">
<Tab name="bla" />
<Tab name="hey" />
</Tabs>
)
The problem here seems to be that the Tabs type parameter of the Tabs component gets inferred as JSX.Element instead of React.FunctionComponentElement<TabProps<N>>[] which has the consequence that the default type string gets used instead, making the invalid value blabla go unnoticed by typescript.
Does this have a workaround? Is this a fundamental limitation of JSX? Is this something that needs a feature request? Is this a bug?