MDX сочетает возможности Markdown и JSX, позволяя создавать динамические документы с компонентами React. Одним из ключевых аспектов работы с MDX в TypeScript или современных JavaScript-проектах является инференс типов. Понимание того, как типы выводятся автоматически и как их можно корректно настроить, позволяет избежать ошибок на этапе компиляции и улучшить интеграцию с React-компонентами.
MDX-файлы компилируются в React-компоненты. При импорте MDX-файла
через TypeScript или с использованием @mdx-js/react
создаётся компонент, тип которого по умолчанию определяется как
React.FC<MDXContentProps>. Интерфейс
MDXContentProps предоставляет возможность передавать
props в MDX-документ, что особенно важно для
динамических данных и управления контентом через параметры.
import { MDXProvider } from '@mdx-js/react';
import MyDocument from './document.mdx';
type MDXProps = {
title: string;
showHeader: boolean;
};
<MyDocument title="Документ" showHeader={true} />
В этом примере TypeScript выводит типы автоматически:
title и showHeader ожидаются в качестве
свойств компонента, если они объявлены в интерфейсе
MDXContentProps. Если типы не указаны явно, TypeScript
может вывести их как any, что снижает безопасность
типов.
MDX позволяет использовать JSX-компоненты прямо внутри Markdown. При этом типы props для таких компонентов также подлежат инференсу.
import { Button } from './Button';
<Button label="Отправить" onCl ick={() => console.log('clicked')} />
Если компонент Button типизирован как:
type ButtonProps = {
label: string;
onClick: () => void;
};
export const Button: React.FC<ButtonProps> = ({ label, onClick }) => (
<button onCl ick={onClick}>{label}</button>
);
TypeScript автоматически выводит типы для использования внутри MDX.
Любая ошибка, например передача onCl ick="строка", будет
поймана на этапе компиляции.
components в MDXProviderMDXProvider позволяет переопределять рендеринг стандартных
Markdown-тегов, таких как h1, p и
a. Типы этих компонентов также могут быть выведены
автоматически:
import { MDXProvider } from '@mdx-js/react';
const components = {
h1: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
<h1 style={{ color: 'red' }} {...props} />
),
a: (props: React.AnchorHTMLAttributes<HTMLAnchorElement>) => (
<a target="_blank" {...props} />
),
};
<MDXProvider components={components}>
<MyDocument />
</MDXProvider>
TypeScript понимает, что каждый компонент должен соответствовать типу props соответствующего HTML-элемента. Это позволяет использовать все стандартные атрибуты без дополнительного указания типов, сохраняя гибкость и безопасность.
Для крупных проектов полезно использовать генерацию типов для
MDX-файлов. С помощью @types/mdx или пакета
mdx-types можно создать декларации:
declare module '*.mdx' {
import { ComponentType } from 'react';
const MDXComponent: ComponentType<Record<string, any>>;
export default MDXComponent;
}
Это позволяет TypeScript автоматически выводить типы при импорте
любого MDX-файла. Для более строгой типизации можно заменить
Record<string, any> на конкретный интерфейс props,
поддерживающий статический контроль типов.
MDXProvider с GenericВ последних версиях MDX можно использовать Generic для передачи типа props, что улучшает автодополнение и проверку типов:
import { MDXProvider, MDXContent } from '@mdx-js/react';
type DocumentProps = { title: string; date: string };
const MyDocument: MDXContent<DocumentProps> = ({ title, date }) => (
<>
<h1>{title}</h1>
<p>{date}</p>
</>
);
Использование Generic позволяет TypeScript автоматически вывести все типы для компонентов MDX, делая возможным строгую проверку всех передаваемых данных.
any, теряется безопасность
типов.MDXContent, чтобы сделать
инференс строго типизированным.MDXProvider.Типы в MDX и TypeScript позволяют не только избегать ошибок, но и создавать гибкую систему переиспользуемых компонентов, где все свойства строго проверяются на этапе компиляции. Это делает работу с динамическими документами безопасной и предсказуемой.