Using TypeScript's React.ComponentType with Emotion 11 and /** @jsxImportSource @emotion/react */
See original GitHub issueDescription:
I’m upgrading a project from Emotion 10 to Emotion 11. There are some parts of the code that use a generic Prop type then use React.ComponentType to specify a component that uses those props. Ultimately something like this:
function example<Props>(Component: React.ComponentType<Props>, props: Props) {
return <Component {...props} />;
}
With Emotion 11 and /** @jsxImportSource @emotion/react */
, the props cannot be assigned to the component:
Type 'Props' is not assignable to type 'IntrinsicAttributes & WithConditionalCSSProp<PropsWithChildren<Props>> & Props & { children?: ReactNode; }'.
Type 'Props' is not assignable to type 'WithConditionalCSSProp<PropsWithChildren<Props>>'.ts(2322)
From what I can gather, TypeScript can’t assign Props
to WithConditionalCSSProp<Props>
due to WithConditionalCSSProp
being a conditional type. TS can’t handle something like the following, even though to the reader it seems intuitive X
would be assignable to Output<X>
:
type Output<T> = T extends string ? T : T;
function example<X>(input: X): Output<X> {
// Type 'X' is not assignable to type 'Output<X>'
return input;
}
Is there any workaround for this issue? I’m not sure if there’s a way I can fix React.ComponentType or there’s a fundamentally different approach I should be taking. Thanks!
Issue Analytics
- State:
- Created 3 years ago
- Reactions:8
- Comments:20 (13 by maintainers)
Top GitHub Comments
It turns out the helper approach didn’t really work for me. I ended up manually asserting the type, using
EmotionJSX.LibraryManagedAttributes
directly. This means that thecss
prop is defined asany
, which is not ideal, but I wasn’t able to come up with a better solution.I will close this issue for now. Thanks.
I’ve found that manually extending the
props
type withProps & WithConditionalCSSProp<Props>
fixes the issue:This makes sense to me -
Props
is still generic and inferred from theComponent
definition, but we’re telling TypeScript theprops
variable should be compatible with theComponent
instance.So exporting a helper along the lines of
type Helper<T> = T & WithConditionalCSSProp<T>
is pretty straightforward, to enableprops: Helper<Props>
and avoid working withWithConditionalCSSProp
directly. That seems promising and I can look into that more next week.