Типизация JavaScript через JSDoc: Руководство по настройке TypeScript Compiler

Используете JSDoc для типизации JavaScript? Узнайте, как настроить TypeScript Compiler для профессиональной проверки типов, генерации деклараций и интеграции в процесс разработки.

Введение: От основ к профессиональной настройке

Если вы уже используете JSDoc для описания типов в вашем JavaScript-коде и ощутили пользу от подсказок в редакторе — сделали только первый, хотя и самый важный, шаг. Мощь этого подхода раскрывается полностью, когда вы выходите за пределы редактора и подключаете проверку типов на уровне всего проекта, в процессе сборки и непрерывной интеграции (CI).

Эта статья — продолжение введения в JSDoc. Здесь не будет объяснений, что такое @type или @param. Вместо этого сфокусируемся на инструментарии и конфигурации, которые превращают набор JSDoc-комментариев в строгую систему типов для всего проекта. Вы научитесь настраивать TypeScript Compiler (tsc) для работы с .js-файлами, генерировать файлы деклараций (.d.ts) и автоматизировать проверки.

Быстрый старт: от нуля до полной проверки за 5 минут

Этот раздел — ваша шпаргалка для немедленного внедрения. Предполагается, что TypeScript уже установлен как dev-зависимость (npm install -D typescript).

Шаг 1: Включение проверки в файле:

Добавьте директиву // @ts-check в начало любого .js-файла, чтобы TypeScript Language Server начал его агрессивно анализировать.

// @ts-check

/** @type {string} */
let greeting = "Hello";
greeting = 100; // Немедленно: Type Error!

Шаг 2: Глобальная настройка проекта (jsconfig.json):

Для применения правил ко всему проекту создайте в корне jsconfig.json. Это аналог tsconfig.json для JavaScript-проектов.

{
"compilerOptions": {
"checkJs": true, // Включает проверку типов для всех .js файлов
"strictNullChecks": true, // Включает одну из строгих опций
"module": "ESNext",
"target": "ES2022"
},
"include": ["src/**/*"] // Какие файлы проверять
}

Ключевая опция checkJs — это «волшебный выключатель», который активирует фоновую проверку типов для всего кода в редакторе.

Шаг 3: Запуск проверки из терминала:

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

{
"scripts": {
"type-check": "tsc --noEmit --project jsconfig.json"
}
}

Запустите npm run type-check. Команда tsc --noEmit запустит компилятор, но не будет создавать никаких выходных файлов — только проверит типы и выведет ошибки в терминал. Это основа для CI.

Генерация файлов .d.ts: Делаем вашу библиотеку дружелюбной к TypeScript

Если создаёте библиотеку на чистом JavaScript, ваши пользователи, работающие в TypeScript-проектах, будут ожидать файлы деклараций типов (.d.ts). Их можно сгенерировать автоматически из JSDoc-комментариев.

Для этого создайте отдельный tsconfig.declaration.json:

{
"include": ["src/**/*.js"], // Исходные .js файлы
"compilerOptions": {
"allowJs": true, // Разрешить обработку .js файлов
"declaration": true, // Генерировать .d.ts файлы
"emitDeclarationOnly": true, // Не выводить .js (у нас они уже есть)
"outDir": "dist/types", // Куда положить .d.ts файлы
"declarationMap": true // Для удобной навигации "Go to Definition"
}
}

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

{
"scripts": {
"build:types": "tsc -p tsconfig.declaration.json"
}
}

После запуска npm run build:types в папке dist/types появятся файлы .d.ts, полностью отражающие типы, описанные в JSDoc. Укажите путь к ним в package.json вашей библиотеки:

{
"types": "./dist/types/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/types/index.d.ts"
}
}
}

Теперь JS-библиотека будет обеспечивать идеальный опыт разработки в TypeScript-проектах.

Продвинутые паттерны JSDoc для сложных сценариев

Когда выходите за рамки базовых типов, JSDoc предоставляет всю необходимую выразительность.

Импорт и переиспользование сложных типов

Для типов, определённых в других файлах (например, в собственном коде или в сторонних библиотеках без типов), используйте @typedef с импортом.

// src/types.js
/**
* @typedef {Object} User
* @property {number} id
* @property {string} name
*/

export {};

// src/controller.js
/**
* @typedef {import('./types.js').User} User
* @typedef {import('some-js-lib').ExternalConfig} Config
*/


/**
* @param {User} user
* @param {Config} config
*/

export function processUser(user, config) { /* ... */ }

Типизация для реактивных и DOM-манипуляций

Работа с DOM API или фреймворками часто требует указания конкретных типов элементов.

// Типизация элемента DOM
/** @type {HTMLInputElement | null} */
const searchInput = document.querySelector('.search-input');

// Типизация в обработчике события
element.addEventListener('click', (/** @type {MouseEvent} */ evt) => {
// evt теперь имеет тип MouseEvent
});

// Типизация для фреймворка (пример с htmx)
htmx.defineExtension("my-ext", {
onEvent: (name, /** @type {CustomEvent} */ event) => {
// event теперь типизирован как CustomEvent
}
});

Обход проверки в исключительных случаях

Иногда TypeScript не может корректно вывести тип, или вы намеренно делаете что-то, что выходит за рамки системы типов. В таких случаях используйте осознанные исключения.

// 1. @ts-ignore - отключает проверку для следующей строки (используйте редко).
// @ts-ignore
const legacyData = getDataFromUnsafeSource();

// 2. @ts-expect-error - ожидает ошибку. Лучшая практика, так как падает, если ошибки нет.
function strictParse(input) {
// Мы уверены, что parse может выбросить ошибку, которую мы обработаем.
// @ts-expect-error
return unsafeParse(input);
}

// 3. Приведение типа (Type Assertion) через JSDoc
const element = /** @type {HTMLElement} */ (document.querySelector('.dynamic-widget'));

Настройка CI/CD

Статическая типизация приносит максимальную пользу, когда она обязательна для всего кода, попадающего в основную ветку. Интегрируйте проверку типов в ваш процесс CI/CD.

Базовый шаг для GitHub Actions (.github/workflows/type-check.yml):

name: Type Check
on: [push, pull_request]
jobs:
type-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '24'
check-latest: true
- run: npm ci
- run: npm run type-check # Скрипт, который мы создали ранее

Этот workflow будет запускаться при каждом пуше и пул-реквесте, блокируя слияние кода, содержащего ошибки типов.

Заключение: JavaScript с типизацией enterprise-уровня

Использование JSDoc в паре с TypeScript Compiler — это не «хак», а легитимная, мощная и промышленно пригодная методология. Она позволяет:

  1. Создавать и поддерживать крупные кодовые базы на чистом JavaScript, не жертвуя надёжностью, которой славится TypeScript.
  2. Иметь итерационный цикл разработки без задержек на сборку, получая при этом всю интеллектуальную помощь редактора.
  3. Построить сквозной процесс гарантии качества — от написания кода до слияния в main — через статический анализ.
  4. Создавать библиотеки, которые одинаково хорошо работают в проектах на JavaScript и TypeScript.

Как показано в первой части руководства, начать использовать JSDoc невероятно просто. А как вы только что узнали, — нет предела глубине его интеграции в профессиональный рабочий процесс. Вы получаете всю мощь экосистемы TypeScript, оставаясь при этом в рамках нативных стандартов веб-платформы.

Начните с настройки jsconfig.json и скрипта type-check сегодня — и ваш JavaScript-код завтра станет значительно более предсказуемым, сопровождаемым и безопасным.

Комментарии


Дополнительные материалы

Предыдущая Статья

Быстрая загрузка CSS через словари сжатия

Следующая Статья

Директива location в Nginx: Руководство с примерами