Типизация метаданных

MDX сочетает возможности Markdown и JSX, позволяя использовать компоненты React внутри документов Markdown. Одним из ключевых аспектов работы с MDX является метаданные документа, которые обычно задаются в виде frontmatter — YAML-блока в начале файла. Корректная типизация метаданных позволяет обеспечить строгий контроль структуры документа и повысить надёжность кода.

Frontmatter и его структура

Frontmatter в MDX оформляется следующим образом:

---
title: "Пример документа"
date: "2026-03-23"
tags:
  - javascript
  - mdx
published: true
---

Каждое поле frontmatter имеет своё предназначение:

  • title — заголовок документа, строка.
  • date — дата публикации, строка в формате ISO.
  • tags — массив тегов, каждая запись строка.
  • published — булев флаг публикации.

Без строгой типизации такие поля могут быть заполнены некорректно, что приведёт к ошибкам при рендеринге или обработке документа на этапе сборки.

Определение типов метаданных в TypeScript

Для обеспечения строгой типизации используется интерфейс TypeScript. Пример интерфейса для frontmatter:

export interface MdxMeta {
  title: string;
  date: string;
  tags: string[];
  published: boolean;
  description?: string;
  author?: string;
}

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

  • Использование обязательных и необязательных полей (?) позволяет гибко настраивать метаданные.
  • Массивы и строки строго типизированы, что предотвращает ошибочные значения.
  • Дополнительные поля можно добавлять по мере необходимости, сохраняя совместимость с существующими документами.

Подключение и использование типов с next-mdx-remote

В проектах на Next.js с использованием next-mdx-remote метаданные передаются через объект frontMatter. Типизацию можно подключить так:

import { MdxMeta } from "./types";

export async function getMdxData(slug: string): Promise<{ meta: MdxMeta; content: string }> {
  const source = fs.readFileSync(`content/${slug}.mdx`, "utf8");
  const { content, data } = matter(source);

  return {
    content,
    meta: data as MdxMeta
  };
}

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

  • data as MdxMeta принудительно задаёт тип метаданных, что позволяет TypeScript проверять корректность полей.
  • Любые ошибки в структуре frontmatter будут выявлены ещё на этапе разработки.
  • Метаданные становятся доступными с автокомплитом и проверкой типов, что облегчает работу с ними в компонентах React.

Валидация и безопасное использование

Даже при строгой типизации иногда требуется дополнительная валидация данных. Для этого применяются библиотеки типа zod или yup:

import { z } from "zod";

const MdxMetaSchema = z.object({
  title: z.string(),
  date: z.string().refine(val => !isNaN(Date.parse(val)), "Неверный формат даты"),
  tags: z.array(z.string()),
  published: z.boolean(),
  description: z.string().optional(),
  author: z.string().optional()
});

export function validateMeta(data: unknown): MdxMeta {
  return MdxMetaSchema.parse(data);
}

Преимущества:

  • Гарантия корректного формата данных.
  • Возможность выдачи информативных ошибок при некорректном frontmatter.
  • Совместимость с TypeScript через z.infer<typeof MdxMetaSchema> для автоматической генерации типов.

Интеграция метаданных в компоненты

После типизации и валидации метаданные можно безопасно использовать в компонентах MDX:

import { MdxMeta } from "./types";

interface Props {
  meta: MdxMeta;
}

export const ArticleHeader = ({ meta }: Props) => (
  <header>
    <h1>{meta.title}</h1>
    <p>{meta.date}</p>
    {meta.tags.length > 0 && (
      <ul>
        {meta.tags.map(tag => (
          <li key={tag}>{tag}</li>
        ))}
      </ul>
    )}
  </header>
);

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

  • Поля frontmatter доступны с полной автоподсказкой.
  • Исключается риск опечаток в названиях полей.
  • Обеспечивается согласованность данных между документами MDX.

Динамическая типизация и расширяемость

Для больших проектов типизацию можно сделать динамической, используя утилиты TypeScript для объединения типов нескольких документов:

export type AllMeta = MdxMeta & { category?: string; series?: string };

Такой подход позволяет:

  • Расширять типы без изменения существующих интерфейсов.
  • Создавать метаданные с дополнительными полями, специфичными для конкретного раздела документации.
  • Поддерживать строгую проверку на уровне компиляции при добавлении новых frontmatter-полей.

Типизация метаданных в MDX играет ключевую роль в обеспечении корректности контента, удобства работы с фронтенд-компонентами и безопасности данных. Строгая типизация в сочетании с валидацией позволяет масштабировать проекты, минимизировать ошибки и ускорять разработку.