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

React中MDX的实际类型是什么?如何精准指定参数类型?

如何在React项目中为MDX指定精准类型?

我在React项目中使用MDX,想明确MDX的实际类型,目前找不到对应的类型定义。我写了一个Main组件,其中自定义的MainProps类里的contentStack字段现在用的是React.JSX.Element[]类型,虽然MDX能适配这个类型,但我希望更精准地限定这个数组只能接受MDX相关的内容。

Main组件代码

'use client'

import styles from "./main.module.css";
import React from "react";
import "./main"


export class MainProps {
    constructor(
        public title: string,
        public contentStack: React.JSX.Element[] = [],
        public sectionOrArticle: "section" | "article" = "section",
    ) {
    }
}

export default function Main(props: { prop: MainProps }): React.JSX.Element {
    if (!props.prop.contentStack) {
        return (
            <main className={styles.main}>
                <h2>{props.prop.title}</h2>
            </main>
        )
    }
    return (
        <main className={styles.main}>
            <h2>{props.prop.title}</h2>
            {
                props.prop.sectionOrArticle !== "article" ?
                    props.prop.contentStack.map((item) => (
                        <section key={props.prop.contentStack!.indexOf(item)}>
                            {item}
                        </section>
                    )) : props.prop.contentStack.map((item) => (
                        <article key={props.prop.contentStack!.indexOf(item)}>
                            {item}
                        </article>
                    ))
            }
        </main>
    )

}

当前使用示例

'use client'

import TaskContent from "./task.mdx"
import React from "react";
import Header from "@/app/components/Header/header"
import Main, {MainProps} from "@/app/components/Main/main"
import "./main"

export default function Index(): React.JSX.Element {
    return (
        <div id="root">
            <Header/>
            <Main prop={
                new MainProps(
                    "Sum all numbers till the given one",
                    [
                        TaskContent({}),
                    ],
                    "article",
                )
            }/>
        </div>
    );
}

解决方案

思路1:精准限定MDX组件类型(推荐)

这种思路让contentStack直接接受MDX组件本身,而非渲染后的JSX元素,更符合React组件的使用规范:

  1. 从@mdx-js/react导入MDX组件的官方类型:
import type { MDXContent } from '@mdx-js/react';
  1. 定义专属的MDX组件类型(语义更清晰,可选):
// MDX组件本质是接受任意props的React函数组件
type MDXComponent = MDXContent;
  1. 修改MainProps中contentStack的类型:
export class MainProps {
    constructor(
        public title: string,
        public contentStack: MDXComponent[] = [], // 替换为MDXComponent数组
        public sectionOrArticle: "section" | "article" = "section",
    ) {
    }
}
  1. 调整Main组件的渲染逻辑,直接在内部调用MDX组件:
export default function Main(props: { prop: MainProps }): React.JSX.Element {
    // 修正数组空值判断,用length更准确
    if (props.prop.contentStack.length === 0) {
        return (
            <main className={styles.main}>
                <h2>{props.prop.title}</h2>
            </main>
        )
    }
    return (
        <main className={styles.main}>
            <h2>{props.prop.title}</h2>
            {
                props.prop.sectionOrArticle !== "article" ?
                    props.prop.contentStack.map((MdxComponent, index) => (
                        // 用索引做key更稳妥,避免indexOf导致的重复key问题
                        <section key={index}>
                            <MdxComponent />
                        </section>
                    )) : props.prop.contentStack.map((MdxComponent, index) => (
                        <article key={index}>
                            <MdxComponent />
                        </article>
                    ))
            }
        </main>
    )
}
  1. 调整使用示例,直接传入MDX组件而非调用后的元素:
export default function Index(): React.JSX.Element {
    return (
        <div id="root">
            <Header/>
            <Main prop={
                new MainProps(
                    "Sum all numbers till the given one",
                    [TaskContent], // 直接传递MDX组件
                    "article",
                )
            }/>
        </div>
    );
}

思路2:限定MDX渲染后的JSX元素(品牌类型)

如果坚持要传入渲染后的JSX元素,且需要区分普通JSX和MDX生成的元素,可以用品牌类型标记MDX元素:

  1. 定义带有品牌标识的MDX元素类型:
// 给普通JSX.Element添加专属标识,区分MDX生成的元素
type MDXElement = React.JSX.Element & { __brand: 'MDX' };
  1. 创建辅助函数,确保MDX组件返回的元素带有品牌标识:
// 辅助函数:调用MDX组件并返回标记后的MDXElement
function renderMDX<T extends Record<string, unknown>>(
    mdxComponent: React.ComponentType<T>,
    props: T
): MDXElement {
    return <mdxComponent {...props} /> as MDXElement;
}
  1. 修改MainProps的contentStack类型为MDXElement[]:
export class MainProps {
    constructor(
        public title: string,
        public contentStack: MDXElement[] = [], // 替换为MDXElement数组
        public sectionOrArticle: "section" | "article" = "section",
    ) {
    }
}
  1. 在使用示例中用辅助函数包裹MDX组件的调用:
export default function Index(): React.JSX.Element {
    return (
        <div id="root">
            <Header/>
            <Main prop={
                new MainProps(
                    "Sum all numbers till the given one",
                    [renderMDX(TaskContent, {})], // 用辅助函数生成MDXElement
                    "article",
                )
            }/>
        </div>
    );
}

补充提示

  • 确保已安装必要依赖:@mdx-js/react(MDX核心依赖)和@types/mdx(TypeScript类型支持)。
  • 第一种思路更简洁易维护,建议优先采用,它直接利用MDX官方类型定义,避免额外的类型断言逻辑。

内容的提问来源于stack exchange,提问作者greg pinakapoging nilalang sa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:42:12