Настройка TypeScript

MDX — это расширение Markdown, которое позволяет использовать JSX внутри Markdown-файлов. При интеграции с TypeScript важно правильно настроить проект, чтобы компилятор понимал как JSX, так и синтаксис TypeScript.


Установка необходимых пакетов

Для корректной работы MDX с TypeScript необходимо установить следующие зависимости:

npm install @mdx-js/react @mdx-js/loader typescript ts-loader
  • @mdx-js/react — обеспечивает рендеринг MDX-компонентов в React.
  • @mdx-js/loader — загрузчик для Webpack, позволяющий компилировать MDX в React-компоненты.
  • typescript — ядро TypeScript.
  • ts-loader — интеграция TypeScript с Webpack.

Если проект использует Vite, можно использовать vite-plugin-mdx вместо ts-loader для упрощённой интеграции.


Конфигурация TypeScript

Создание файла tsconfig.json с правильными настройками критично для корректного распознавания MDX:

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "lib": ["DOM", "ESNext"],
    "jsx": "react-jsx",
    "moduleResolution": "node",
    "allowJs": true,
    "checkJs": false,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  },
  "include": ["src/**/*", "**/*.mdx"],
  "exclude": ["node_modules"]
}

Ключевые моменты:

  • jsx: "react-jsx" — использование новой трансформации JSX, поддерживаемой React 17+.
  • include: ["**/*.mdx"] — обязательно добавление MDX-файлов, иначе TypeScript их не увидит.
  • skipLibCheck: true — ускоряет сборку, пропуская проверку типов в сторонних библиотеках.

Создание типов для MDX

TypeScript не понимает синтаксис MDX по умолчанию. Для корректной типизации создаётся файл с декларациями типов, например, src/types/mdx.d.ts:

declare module "*.mdx" {
  import { ComponentType, ReactElement } from "react";

  const MDXComponent: ComponentType<{ [key: string]: any }>;
  export default MDXComponent;
}

Это позволит импортировать MDX-файлы как React-компоненты:

import Content from './content.mdx';

function App() {
  return ;
}

Настройка Webpack для TypeScript и MDX

В Webpack конфигурации нужно объединить ts-loader и @mdx-js/loader:

module.exports = {
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      },
      {
        test: /\.mdx$/,
        use: [
          {
            loader: 'babel-loader',
            options: { presets: ['@babel/preset-react'] }
          },
          '@mdx-js/loader'
        ]
      }
    ]
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js', '.jsx', '.mdx']
  }
};

Особенности:

  • Порядок загрузчиков важен: сначала babel-loader для JSX-трансформации, затем @mdx-js/loader для MDX.
  • Расширения .mdx добавляются в resolve.extensions для корректного импорта без указания расширений.

Интеграция с Vite

Для проектов на Vite используется плагин vite-plugin-mdx:

import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import mdx from 'vite-plugin-mdx';

export default defineConfig({
  plugins: [react(), mdx()],
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx', '.mdx']
  }
});

TypeScript конфигурация аналогична Webpack, включая include для MDX-файлов и декларации типов.


Совместимость с ESLint и Prettier

MDX-файлы можно линтить с помощью eslint-plugin-mdx. В .eslintrc.js добавляется:

module.exports = {
  extends: [
    'plugin:mdx/recommended',
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended'
  ],
  settings: { react: { version: 'detect' } },
  overrides: [
    {
      files: ['*.mdx'],
      parser: '@typescript-eslint/parser'
    }
  ]
};

Это обеспечивает поддержку TypeScript и JSX внутри MDX при проверке кода.


Настройка импорта глобальных компонентов

MDX часто использует общие React-компоненты. В TypeScript важно корректно типизировать MDXProvider:

import { MDXProvider } from '@mdx-js/react';
import CustomHeading from './components/CustomHeading';

const components = {
  h1: CustomHeading
};

function App({ children }: { children: React.ReactNode }) {
  return {children};
}

Типизация компонентов позволяет TypeScript проверять правильность пропсов для элементов, заменяемых через MDX.


Работа с динамическим импортом MDX

Для оптимизации загрузки можно использовать динамический импорт:

import { lazy, Suspense } from 'react';

const DynamicContent = lazy(() => import('./content.mdx'));

function App() {
  return (
    Загрузка...
}> ); }

TypeScript корректно понимает тип MDXComponent благодаря ранее созданной декларации.