TypeScript中如何判断传入的React图标是CustomIcon还是MUI图标?
解决方案
首先,React元素的type属性可以直接用来区分不同组件生成的元素——当你传入<CustomIcon />时,这个元素的type就是CustomIcon组件本身;而MUI图标元素的type是对应的MUI组件(比如HomeIcon)。利用这一点就能实现条件判断,再通过cloneElement给图标添加额外属性。
基础实现(仅传入React元素的情况)
假设你的ParentComponentProps只接收渲染好的React元素(和你给出的调用示例一致),可以这样处理:
import { ReactElement, cloneElement } from 'react'; import { SvgIconProps } from '@mui/material/SvgIcon'; // 自定义CustomIcon的props类型 type CustomIconProps = { className?: string; // 你的其他自定义属性 }; type ParentComponentProps = { icon: ReactElement<SvgIconProps> | ReactElement<CustomIconProps>; }; const ParentComponent = ({ icon }: ParentComponentProps) => { // 判断当前元素是否为CustomIcon生成 const isCustomIcon = icon.type === CustomIcon; // 根据类型添加不同的额外属性 const extraProps = isCustomIcon ? { className: `${icon.props.className || ''} custom-icon-extra-class` } : { className: `${icon.props.className || ''} mui-icon-extra-class` }; // 克隆原图标元素并合并属性 const enhancedIcon = cloneElement(icon, extraProps); return <div>{enhancedIcon}</div>; };
兼容传入组件类型的情况
如果你的ParentComponentProps确实允许传入CustomIcon组件本身(而非渲染后的元素),需要先区分传入的是组件还是React元素:
import { ReactElement, cloneElement, isValidElement } from 'react'; import { SvgIconProps } from '@mui/material/SvgIcon'; type ParentComponentProps = { icon: ReactElement<SvgIconProps> | typeof CustomIcon; }; const ParentComponent = ({ icon }: ParentComponentProps) => { let enhancedIcon; if (isValidElement(icon)) { // 处理传入的React元素 const isCustomIcon = icon.type === CustomIcon; const extraProps = isCustomIcon ? { className: 'custom-icon-extra' } : { className: 'mui-icon-extra' }; enhancedIcon = cloneElement(icon, extraProps); } else { // 处理传入的CustomIcon组件本身,直接渲染并附加属性 enhancedIcon = <icon className="custom-component-extra" />; } return <div>{enhancedIcon}</div>; };
应对组件被高阶组件包装的情况
如果CustomIcon被memo等高阶组件包装过,直接判断icon.type === CustomIcon会失效,这时候可以给CustomIcon添加一个唯一标识来做判断:
// 给CustomIcon添加自定义标识 const CustomIcon = (props: CustomIconProps) => { // ...组件实现 }; CustomIcon.isCustomComponent = true; // 在ParentComponent中判断 const isCustomIcon = typeof icon.type === 'function' && (icon.type as any).isCustomComponent;
为什么typeof/instanceof不适用?
typeof只能判断出组件是函数类型,但MUI图标和你的CustomIcon都是函数组件,无法区分;instanceof仅适用于类组件,对函数组件无效;- TypeScript的类型是编译时信息,运行时无法直接通过类型做判断,必须依赖运行时可访问的标识或属性。
内容的提问来源于stack exchange,提问作者CloudBurst
相关产品推荐
相关产品推荐

