Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як правильно публікувати типи npm-пакета через types і exports у package.json?

Пакет на TypeScript публікує скомпільований JavaScript і файли декларацій .d.ts (з declaration: true). Як їх знайде споживач - вирішує package.json.

Сучасний варіант - поле exports з умовою types:

{
  "name": "@acme/money",
  "type": "module",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "import": "./dist/index.js",
      "require": "./dist/index.cjs"
    },
    "./format": {
      "types": "./dist/format.d.ts",
      "import": "./dist/format.js"
    }
  },
  "files": ["dist"]
}

Правила, які найчастіше порушують:

  • types - першою умовою в кожному об'єкті. Умови перевіряються по порядку, і TypeScript візьме першу підходящу. Якщо import стоїть раніше, компілятор може «знайти» JavaScript замість декларацій;
  • кожна точка входу в exports має власні types - верхньорівневе поле types для підшляхів не діє;
  • подвійний пакет (ESM + CommonJS) потребує окремих декларацій для кожного формату (index.d.ts і index.d.cts). Одні .d.ts на обидва формати TypeScript інтерпретує в одному режимі - і споживачі з іншим форматом отримують неправильні типи (класична проблема «masquerading as ESM/CJS»);
  • files має включати каталог з .d.ts, інакше їх не буде в опублікованому архіві.

Старе поле types/typings у корені - для споживачів зі старими налаштуваннями резолюції. Опції moduleResolution: node10 у TypeScript 6/7 вже немає, тож сучасні споживачі читають exports; поле в корені можна лишити як запасний варіант.

Залежності типів: якщо публічні декларації посилаються на типи іншого пакета (import type { Request } from 'express'), той пакет (@types/express) має бути в dependencies чи peerDependencies, а не в devDependencies - інакше у споживачів типи зламаються.

Перевірка перед публікацією:

  • @arethetypeswrong/cli - перевіряє, що типи правильно резолвляться для всіх режимів (node16 ESM/CJS, bundler);
  • publint - узгодженість exports, files і реальних файлів;
  • npm pack --dry-run - що саме потрапить в архів.

isolatedDeclarations спрощує генерацію декларацій сторонніми інструментами (і пришвидшує збирання), але вимагає явних типів на експортах.

Докладніше в документації: Публікація декларацій

Схожі питання