When using styled components >=4.1.0 or emotion >=10 there will be type errors if material ui components are styled.
No build or type errors are expected when styling material ui components with styled components or emotion.
A lot of type errors like
TS2740: Type '{ children: string; }' is missing the following properties from type 'Pick<Pick<(Pick<PaperProps, "style" | "title" | "children" | "className" | "color" | "id" | "lang" | "role" | "tabIndex" | "elevation" | "aria-activedescendant" | "aria-atomic" | ... 245 more ... | "innerRef"> & RefAttributes<...>) | PropsWithChildren<...>, "ref
" | ... 257 more ... | "innerRef"> & Partial<...>, "ref...': ref, style, title, className, and 254 more.
or
TS2322: Type '{ children: Element; component: string; }' is not assignable to type 'IntrinsicAttributes & Pick<Pick<DefaultComponentProps<{ props: { dense?: boolean | undefined; disablePadding?: boolean | undefined; subheader?: ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<...>)> | n
ull) | (new (props: any) => Component<...>)> | undefine...'.
Property 'component' does not exist on type 'IntrinsicAttributes & Pick<Pick<DefaultComponentProps<{ props: { dense?: boolean | undefined; disablePadding?: boolean | undefined; subheader?: ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<...>)> | null) | (new (props: any) => Component<...>)
> | undefine...'.
I don't know for sure, but I think there could be two different issues in the demo.
The first is a simple styled Paper component. When downgrading to styled components <=4.0.3, this issue will be fixed.
The second one is a styled List component. Styled List components will work, as long as there are no prop attributes set. If e.g. component="nav" is added, there will be an error. Downgrading to styled-components 4.0.3 won't work here. But downgrading to material ui 3.9.2, will.
Both cases are shown in the demo.
I want to style material ui components using styled-components library.
| Tech | Version |
|--------------|---------|
| Material-UI |4.0.0 |
| React |16.8.17|
| TypeScript |3.4.5|
This is a limitation of typescript. See https://github.com/mui-org/material-ui/issues/15759#issuecomment-493994852 for the recommended solution i.e. casting the wrapped component back to the original type. I understand this is not ideal but there are other limitations in typescript that block other approaches. For these simple applications where props available from the HOC are of no interest type casting seems good enough. For more complex examples follow #15827 which should have a proposal by the end of this week.
Casting back to the original type would be possible. But its a hard change. We have a large code base. And adding casts to each and every component could break the upgrade for us.
I also tried to implement the type cast to the demo under https://github.com/Mario-Eis/materialui-styled-test.
The good news: The issue shown in the demo with the Paper Component, seems to be fixed.
Unfortunately
const StyledList = styled(List)`
background-color: blue;
text-align: center;
` as List;
results in
TS2749: 'List' refers to a value, but is being used as a type here.
I pushed the workaround to the demo repo.
List is now defined as a variable.
declare const List: OverridableComponent<{
props: {
dense?: boolean;
disablePadding?: boolean;
subheader?: React.ReactElement;
};
defaultComponent: 'ul';
classKey: ListClassKey;
}>;
The workaround doesn't seem to work any more.
const StyledList = styled(List)`
background-color: blue;
text-align: center;
` as typeof List;
Seems codemodable. Though you have to be aware that any type information about props handled by styled is lost.
Thanks! I updated the demo repo. It compiles without errors now.
Only the IDE (IntelliJ) shows a warning that there is a missing required attribute "component". But I think that will be another issue. Will investigate that.
@Mario-Eis
Hello.
This should help:
const StyledList = styled<ComponentType<ListProps>>(List)`
background-color: blue;
text-align: center;
`;
Closing as it was labeled as a limitation of TypeScript and has a workaround.
@oliviertassinari why shouldn't the workaround be part of MUI itself though?
Most helpful comment
@oliviertassinari why shouldn't the workaround be part of MUI itself though?