传递Material UI图标作为组件Props时应使用何种TypeScript类型?
问题背景
我想把Material UI的图标作为Props传递给组件,但不知道该用什么类型,尝试了两种类型定义都报错了。
初始代码示例
import {OverridableComponent} from "@mui/material/OverridableComponent"; import {SvgIconTypeMap} from "@mui/material"; interface IconButtonProps { children: OverridableComponent<SvgIconTypeMap<{}, "svg">> & {muiName: string}; disabled?: boolean; } const IconButton = ({ children, disabled = false, }: IconButtonProps) => { return ( <Button disabled={disabled}> {children} </Button> ) }
组件使用方式
import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline'; <IconButton><AddCircleOutlineIcon/></IconButton>
出现的错误
Type 'Element' is not assignable to type 'OverridableComponent<SvgIconTypeMap<{}, "svg">>'. Type 'Element' provides no match for the signature '
(props: { component: C; } & { children?: ReactNode; classes?: Partial | undefined; color?: "disabled" | ... 8 more ... | undefined; ... 6 more ...; viewBox?: string | undefined; } & CommonProps & DistributiveOmit<...>): Element | null'.
另一种尝试的代码
import {SvgIconComponent} from "@mui/icons-material"; children: SvgIconComponent;
同样出现了上述相同的错误提示。
解决方案
你当前的问题核心是:定义的children类型是图标组件本身(比如AddCircleOutlineIcon这个函数组件),但实际传递的是组件渲染后的Element节点(<AddCircleOutlineIcon/>),类型不匹配导致报错。
根据不同需求,有两种解决方式:
场景1:传递渲染好的图标Element(对应你当前的使用方式)
直接把children的类型定义为React.ReactNode即可,这是React中最通用的子元素类型,兼容所有可渲染内容:
import { ReactNode } from 'react'; interface IconButtonProps { children: ReactNode; disabled?: boolean; }
场景2:传递图标组件本身(而非渲染后的节点)
如果需要在IconButton内部控制图标的props(比如颜色、大小),可以传递组件本身,此时使用SvgIconComponent类型,同时调整使用方式:
import { SvgIconComponent } from "@mui/icons-material"; import { Button } from "@mui/material"; interface IconButtonProps { Icon: SvgIconComponent; disabled?: boolean; iconColor?: string; } const IconButton = ({ Icon, disabled = false, iconColor = 'inherit' }: IconButtonProps) => { return ( <Button disabled={disabled}> <Icon color={iconColor} /> </Button> ) } // 使用方式 <IconButton Icon={AddCircleOutlineIcon} />
按实际需求选择对应的类型定义,就能解决类型不匹配的问题。
内容的提问来源于stack exchange,提问作者four-eyes

