You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MUI的TypeScript自定义组件:实现component prop动态类型

MUI自定义组件动态Prop类型与Component类型适配

一、类型定义:实现MediaTypeMap与MediaProps

按照MUI核心包的风格,我们可以通过映射接口+泛型条件类型实现动态Prop类型:

  1. 定义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>;
  1. 定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:25:19