В экосистеме MDX ключевую роль играют провайдеры, которые позволяют интегрировать React-компоненты и контент Markdown с расширениями JSX. Типизация провайдеров критична для обеспечения безопасного и предсказуемого взаимодействия компонентов внутри MDX-документов.
MDX предоставляет MDXProvider, который принимает объект
components — словарь компонентов, используемых для замены
стандартных HTML-тегов. Типизация этого объекта выполняется через
интерфейсы:
import { MDXProviderComponents } from '@mdx-js/react';
const components: MDXProviderComponents = {
h1: (props) => <h1 style={{ color: 'red' }} {...props} />,
p: (props) => <p style={{ fontSize: 16 }} {...props} />,
};
MDXProviderComponents позволяет строго указать
соответствие тега HTML и компонента
React, обеспечивая проверку типов на этапе компиляции. Это
исключает ошибки при попытке передать неподдерживаемый компонент для
стандартного тега.
MDX поддерживает расширение типов с помощью обобщений. Если требуется использовать собственные теги или расширенные свойства, можно определить собственный интерфейс:
import { MDXProviderComponents } from '@mdx-js/react';
interface CustomComponents {
MyButton: React.FC<{ label: string; onClick: () => void }>;
}
const customComponents: MDXProviderComponents & CustomComponents = {
h1: (props) => <h1 {...props} />,
MyButton: ({ label, onClick }) => <button onCl ick={onClick}>{label}</button>,
};
Использование Generics гарантирует, что любая ошибка в передаваемых пропсах будет выявлена на этапе компиляции TypeScript, что особенно важно для больших MDX-проектов с множеством кастомных компонентов.
Внутри MDX используется контекст MDXContext, который
позволяет компонентам получать доступ к текущему набору компонентов:
import { useMDXComponents, MDXProvider } from '@mdx-js/react';
const components = {
h2: (props) => <h2 style={{ fontWeight: 'bold' }} {...props} />,
};
const Component = () => {
const allComponents = useMDXComponents();
const H2 = allComponents.h2;
return <H2>Заголовок второго уровня</H2>;
};
<MDXProvider components={components}>
<Component />
</MDXProvider>
Функция useMDXComponents возвращает типизированный
объект компонентов, что позволяет безопасно использовать их внутри
вложенных компонентов. Типизация здесь особенно важна при интеграции с
TypeScript, так как она предотвращает обращение к несуществующим
компонентам или неверные пропсы.
MDX позволяет заменять компоненты динамически, что удобно при создании тем или скинов для документации:
const defaultComponents = {
p: (props) => <p style={{ color: 'black' }} {...props} />,
};
const darkModeComponents = {
p: (props) => <p style={{ color: 'white' }} {...props} />,
};
const currentTheme = 'dark';
<MDXProvider components={currentTheme === 'dark' ? darkModeComponents : defaultComponents}>
<MDXContent />
</MDXProvider>
Для безопасного переключения тем полезно определить объединённый тип:
type ThemeComponents = typeof defaultComponents & typeof darkModeComponents;
Это гарантирует, что любая комбинация тем соответствует строго типизированному контракту компонентов.
MDXContent при использовании кастомных провайдеровMDX-файлы при компиляции становятся компонентами React с типами, автоматически генерируемыми TypeScript. Чтобы расширить их функциональность, можно явно указать пропсы:
import { MDXContent } from './example.mdx';
interface MDXProps {
components?: MDXProviderComponents & { MyButton?: React.FC<{ label: string }> };
}
<MDXContent components={{ MyButton: ({ label }) => <button>{label}</button> }} />;
Такое определение позволяет использовать собственные компоненты внутри MDX без потери типизации и с полной поддержкой автодополнения.
MDXComponents для строгого контроляДля проектов с большим количеством MDX-документов рекомендуется создать отдельный интерфейс всех компонентов:
interface MDXComponents {
h1: React.FC<React.HTMLAttributes<HTMLHeadingElement>>;
h2: React.FC<React.HTMLAttributes<HTMLHeadingElement>>;
p: React.FC<React.HTMLAttributes<HTMLParagraphElement>>;
MyButton: React.FC<{ label: string; onClick: () => void }>;
}
const components: MDXComponents = { ... };
Такой подход обеспечивает:
Эта методика позволяет использовать MDX максимально безопасно и гибко, обеспечивая строгую типизацию всех компонентов, что особенно важно для масштабируемых проектов, где документы и React-компоненты активно взаимодействуют.