基于MUI的TypeScript自定义组件:实现component prop动态类型
MUI自定义组件动态Prop类型与Component类型适配
一、类型定义:实现MediaTypeMap与MediaProps
按照MUI核心包的风格,我们可以通过映射接口+泛型条件类型实现动态Prop类型:
- 定义
MediaTypeMap,映射不同component对应的dynamicallyTypedProp类型:
import type { ElementType, PropsOf } from '@mui/material'; // 定义不同组件对应的dynamicallyTypedProp类型 interface MediaTypeMap { 'a': string; // component为a标签时,dynamicallyTypedProp对应href字符串 'img': string; // component为img标签时,dynamicallyTypedProp对应src字符串 // 可扩展自定义组件的类型映射,例如: // MyCustomCard: { cardId: number }; } // 覆盖所有支持的组件类型(包含原生标签与自定义组件) type SupportedMediaComponent = keyof MediaTypeMap | Exclude<ElementType, keyof MediaTypeMap>;
- 定义
MediaProps泛型类型,根据传入的component自动推导dynamicallyTypedProp类型:
type MediaProps<C extends SupportedMediaComponent> = { component?: C; // 动态类型逻辑:若C是MediaTypeMap的键,使用对应类型;否则使用默认类型(可按需调整) dynamicallyTypedProp: C extends keyof MediaTypeMap ? MediaTypeMap[C] : unknown; } & Omit<PropsOf<C>, 'component' | 'dynamicallyTypedProp'>;
这样当你传入component="a"时,dynamicallyTypedProp会被自动推断为string;传入component="img"时同理;若传入自定义组件,TypeScript会自动适配该组件的原生Props,同时dynamicallyTypedProp使用默认的unknown类型(可根据业务需求修改默认值)。
二、组件实现:无需useThemeProps的Component类型适配
在@mui/material中,可通过React.forwardRef结合泛型参数实现组件类型支持,无需依赖@mui/joy的useThemeProps:
import React from 'react'; import { Box } from '@mui/material'; const Media = React.forwardRef<unknown, MediaProps<SupportedMediaComponent>>( ({ component: Component = Box, dynamicallyTypedProp, ...props }, ref) => { // 根据组件类型,将dynamicallyTypedProp映射为对应属性 const componentProps = { ...props, ...(Component === 'a' && { href: dynamicallyTypedProp }), ...(Component === 'img' && { src: dynamicallyTypedProp }), // 自定义组件的属性映射逻辑 // ...(Component === MyCustomCard && { cardId: dynamicallyTypedProp }), }; return <Component ref={ref} {...componentProps} />; } ); Media.displayName = 'Media'; export default Media;
三、问题针对性解答
问题1:动态Prop类型实现
上述MediaTypeMap+MediaProps的组合,就是MUI核心包(如Button组件)的实现思路——通过映射接口定义不同组件的Prop类型关联,再用泛型条件类型完成自动推导。你参考的Button源码中,正是通过ButtonTypeMap映射不同component的Props规则,再结合ButtonProps泛型实现动态类型适配。
问题2:Component类型适配(不用useThemeProps)
@mui/material的组件通常通过forwardRef+泛型Props处理component类型,不需要依赖@mui/joy的useThemeProps。上面的实现中,通过MediaProps<SupportedMediaComponent>作为泛型参数,让TypeScript自动推断传入component对应的原生Props,同时完成dynamicallyTypedProp的类型适配。
内容的提问来源于stack exchange,提问作者maeertin
相关产品推荐
相关产品推荐

