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... ♀️