如何解决Material UI v5中styled() SVG图标兼容React SVG组件的类型报错
我有一段可运行的代码,但props类型设为any,重构到MUI v5前用MUI v4的makeStyles时没问题。代码如下:
// SVG Icons components import import { ReactComponent as AppLogo } from '../../../icons/appLogo.svg'; // Styled Mui Component export const StyledLogo = styled(SvgIcon)<any>(({ theme }) => ({ backgroundColor: 'white', fill: theme.palette.primary.main, width: 50, height: 50, borderRadius: 10, margin: 5, verticalAlign: 'middle', })); <StyledLogo component={AppLogo} viewBox='0 0 700 700' />
移除any类型后,component属性报错:
Type '{ component: FunctionComponent<SVGProps & { title?: string | undefined; }>; viewBox: string; }' is not assignable to type 'IntrinsicAttributes & { children?: ReactNode; classes?: Partial | undefined; color?: OverridableStringUnion<"inherit" | ... 7 more ... | "warning", SvgIconPropsColorOverrides> | undefined; ... 6 more ...; viewBox?: string | undefined; } & CommonProps & Omit<...> & MUIStyledCommonProps<...> & { ...; }'.
Property 'component' does not exist on type 'IntrinsicAttributes & { children?: ReactNode; classes?: Partial | undefined; color?: OverridableStringUnion<"inherit" | ... 7 more ... | "warning", SvgIconPropsColorOverrides> | undefined; ... 6 more ...; viewBox?: string | undefined; } & CommonProps & Omit<...> & MUIStyledCommonProps<...> & { ...; }'.ts(2322)
(property) component: React.FunctionComponent<React.SVGProps & {
title?: string | undefined;
AppLogo的类型:
const AppLogo: React.FunctionComponent<React.SVGProps & {
title?: string | undefined;
}>
希望不使用any类型解决兼容问题。
方法1:显式传入SvgIconProps类型
MUI的styled工具需要明确组件的props类型,直接用SvgIconProps作为泛型参数即可,它本身已包含component属性的定义:
import { SvgIcon, SvgIconProps } from '@mui/material'; export const StyledLogo = styled(SvgIcon)<SvgIconProps>(({ theme }) => ({ backgroundColor: 'white', fill: theme.palette.primary.main, width: 50, height: 50, borderRadius: 10, margin: 5, verticalAlign: 'middle', }));
这样StyledLogo就能正确识别component属性,无需使用any。
方法2:自定义扩展props类型(如需额外属性)
如果需要给StyledLogo添加自定义props,可以基于SvgIconProps扩展:
import { SvgIcon, SvgIconProps } from '@mui/material'; type StyledLogoProps = SvgIconProps & { customSize?: number; // 示例自定义属性 }; export const StyledLogo = styled(SvgIcon)<StyledLogoProps>(({ theme, customSize = 50 }) => ({ backgroundColor: 'white', fill: theme.palette.primary.main, width: customSize, height: customSize, borderRadius: 10, margin: 5, verticalAlign: 'middle', }));
这种方式既保留SvgIcon的原生props,又支持自定义属性,完全规避any。
方法3:直接包裹SVG组件(替代component属性)
无需借助SvgIcon的component属性,直接将AppLogo作为styled的基础组件,类型会自动推导:
export const StyledLogo = styled(AppLogo)(({ theme }) => ({ backgroundColor: 'white', fill: theme.palette.primary.main, width: 50, height: 50, borderRadius: 10, margin: 5, verticalAlign: 'middle', })); // 使用方式 <StyledLogo viewBox='0 0 700 700' />
这种方式更简洁,彻底避免类型兼容问题。
内容的提问来源于stack exchange,提问作者Richardson

