This is an offshoot of TypeScript type for React FunctionComponent that returns exactly one IntrinsicElement.
React defines
declare namespace JSX {
type Element = React.ReactElement<any, any>;
}
And while I can't find it in @types/react/index.d.ts, rendering a <Fragment> returns a JSX.Element. So, if I want to define a type for a function that returns exactly one HTML element (i.e. not a Fragment unless it has exactly one child, which would defeat its purpose), I somehow need to limit my return type to something like
type IntrinsicFC =
() => Exclude<JSX.IntrinsicElements[keyof JSX.IntrinsicElements], ReactElement<any, any>>;
(Note: Exclude<..., ReactElement<any, any>> does not mean what I expected it to; it seems to be identical to JSX.IntrinsicElements[keyof JSX.IntrinsicElements] though I don't understand why. But, for the sake of this question, assume I did know the right type for what I tried to express.)
However, any is the death of strong typing, and since every HTML Element extends ReactElement<any, any>, this would make my type () => never.
Is there a way to exclude a type which is a type alias for SomeGenericType<any>?
My latest failed attempt at making an IntrinsicFC is:
type IntrinsicElement = JSX.IntrinsicElements[keyof JSX.IntrinsicElements];
type IntrinsicFC<P = void> =
((props: P) => IntrinsicElement) extends ((props: P) => JSX.IntrinsicElements[infer U & keyof JSX.IntrinsicElements])
? U extends keyof JSX.IntrinsicElements
? ((props: P) => JSX.IntrinsicElements[U])
: never
: never;
This, however, results in type IntrinsicFC<P = {}> = never;, because IntrinsicElement always extends JSX.IntrinsicElements[keyof JSX.IntrinsicElements] as it is the very same definition.
I suspected that when the React team wrote the declaration file, they meant JSX.Element to be defined as
type Element = React.ReactElement<unknown>;
but that the type predates TypeScript v3.0.0, which introduced the unknown type, and changing it now would be a breaking change. However, I just tried manually changing the type declaration, and it still doesn't work, so... ♀️