Написание документации для TypeScript проекта: от А до Я

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему документация — это инвестиция, а не трата времени

Каждый разработчик сталкивался с ситуацией: возвращаясь к собственному коду через месяц, вы с трудом вспоминаете, зачем нужен тот или иной параметр. Что уж говорить о новых членах команды, которые пытаются разобраться в вашем проекте. Качественная документация для TypeScript проекта — это не просто приятное дополнение, а критически важный элемент, который ускоряет онбординг, снижает количество багов и делает код поддерживаемым.

TypeScript, будучи надстройкой над JavaScript, предоставляет мощную систему типов. Однако типы сами по себе не всегда отвечают на вопрос «почему». Документация восполняет этот пробел. В этой статье мы разберем полный цикл: от выбора стиля комментариев до генерации статического сайта с документацией.

1. Основы: JSDoc, TSDoc и TypeScript

Для документирования TypeScript кода исторически сложились два основных стандарта: JSDoc и TSDoc. JSDoc — это старый добрый формат, который пришёл из мира JavaScript. TSDoc — более современный стандарт, оптимизированный специально для TypeScript. Оба подхода используют комментарии в формате /** ... */.

Рассмотрим базовый пример с использованием JSDoc:

/**
 * Вычисляет сумму двух чисел.
 * @param a - Первое слагаемое
 * @param b - Второе слагаемое
 * @returns Сумма a и b
 */
function add(a: number, b: number): number {
    return a + b;
}

А вот как это выглядит в стиле TSDoc с использованием тегов @param и @returns:

/**
 * Вычисляет сумму двух чисел.
 * @param a - Первое слагаемое
 * @param b - Второе слагаемое
 * @returns Сумма a и b
 */
function add(a: number, b: number): number {
    return a + b;
}

Разница минимальна, но TSDoc добавляет поддержку специфических для TypeScript конструкций, таких как дженерики и условные типы.

1.1 Документирование интерфейсов и типов

Особое внимание стоит уделить интерфейсам и типам. Они являются «скелетом» TypeScript проекта. Вот пример хорошо документированного интерфейса:

/**
 * Представляет пользователя системы.
 */
interface User {
    /** Уникальный идентификатор пользователя */
    id: string;
    /** Полное имя пользователя */
    name: string;
    /** Email адрес (должен быть уникальным) */
    email: string;
    /** Дата последнего входа в систему (опционально) */
    lastLogin?: Date;
    /** Роль пользователя в системе */
    role: 'admin' | 'user' | 'moderator';
}

Обратите внимание: каждый параметр интерфейса имеет свой /** ... */ комментарий. Это позволяет IDE (например, VS Code) показывать подсказки при использовании этого интерфейса.

2. Продвинутые техники: дженерики и условные типы

TypeScript славится своей системой типов, и документация должна отражать её сложность. Особенно это касается дженериков (generic types) и условных типов (conditional types).

Рассмотрим пример дженерика с документацией:

/**
 * Создаёт массив из одного элемента с типом T.
 * @template T - Тип элемента, который будет помещён в массив
 * @param item - Элемент для обёртывания
 * @returns Массив, содержащий переданный элемент
 */
function wrapInArray<T>(item: T): T[] {
    return [item];
}

Тег @template явно указывает, что такое T. Это особенно полезно, когда дженериков несколько или они имеют сложную взаимосвязь.

Для условных типов документация становится ещё важнее. Пример:

/**
 * Извлекает тип значения из Promise, если передан Promise.
 * Иначе возвращает исходный тип.
 * @template T - Тип, который может быть Promise или нет
 * @example
 * // Для Promise<number> вернёт number
 * type Result = UnwrapPromise<Promise<number>>; // number
 * // Для string вернёт string
 * type Result2 = UnwrapPromise<string>; // string
 */
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

Блок @example здесь — лучший друг разработчика. Он показывает, как тип работает на практике, что гораздо понятнее сухого описания.

3. Инструменты генерации документации

Писать комментарии — это полдела. Чтобы команда могла ими пользоваться, нужно сгенерировать удобочитаемую документацию. Для TypeScript лучшим инструментом является TypeDoc. Он преобразует ваши JSDoc/TSDoc комментарии в статический HTML-сайт.

3.1 Установка и настройка TypeDoc

Установка проста:

npm install --save-dev typedoc

Добавьте скрипт в package.json:

{
  "scripts": {
    "docs": "typedoc --out docs src"
  }
}

Команда npm run docs просканирует все файлы в папке src и сгенерирует документацию в папку docs.

3.2 Конфигурация TypeDoc

Для более тонкой настройки создайте файл typedoc.json в корне проекта:

{
  "entryPoints": ["src/index.ts"],
  "out": "docs",
  "exclude": ["**/node_modules/**", "**/*.test.ts"],
  "name": "My TypeScript Library",
  "includeVersion": true,
  "excludePrivate": true,
  "excludeProtected": true
}

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

4. Лучшие практики и частые ошибки

На основе многолетнего опыта работы с TypeScript проектами, можно выделить несколько золотых правил:

  • Документируйте «почему», а не «что». Код и так показывает, что он делает. Комментарии должны объяснять причину выбора именно такого решения.
  • Не дублируйте типы. Если тип переменной указан в коде (name: string), не пишите в комментарии «имя — строка». Лучше напишите «полное имя пользователя в формате "Имя Фамилия

Блоги

Рекомендаций по книгам