Якщо в пакета немає власних типів і пакета @types/..., TypeScript повідомляє «Could not find a declaration file for module 'tiny-slug'» і вважає імпорт any (або дає помилку в строгому режимі).
Крок 1 - оголошення модуля в проєкті:
// src/types/tiny-slug.d.ts
declare module 'tiny-slug' {
export interface SlugOptions {
separator?: string;
lower?: boolean;
}
export default function slugify(text: string, options?: SlugOptions): string;
export function isSlug(value: string): boolean;
}
Файл має бути скриптом (без import/export на верхньому рівні) і потрапляти в include.
Крок 2 - описати реальну форму експорту. Тут найчастіше помиляються:
- ESM
export default- як у прикладі; - CommonJS
module.exports = fn- у декларації цеexport = fn:
declare module 'legacy-lib' {
function legacy(input: string): string;
namespace legacy {
const version: string;
}
export = legacy;
}
Імпортувати такий модуль: import legacy from 'legacy-lib' (з esModuleInterop, який у TypeScript 6/7 завжди увімкнений).
Як перевірити форму - подивитися в код пакета (main/exports у його package.json) і що реально повертає require/import у Node.js.
Крок 3 - описувати лише використане. Не обов'язково типізувати весь API бібліотеки - досить того, що викликає ваш код. Решту можна додати пізніше.
Швидкий тимчасовий варіант:
declare module 'tiny-slug'; // усе з пакета - any
Помилка зникає, але й перевірки теж. Варто лише як тимчасовий захід.
Типи для глобальної бібліотеки (підключена через <script>, створює window.Chart) - declare const Chart: ... у глобальному .d.ts.
Що далі:
- якщо декларації якісні й бібліотека популярна - запропонувати їх у DefinitelyTyped (пакет
@types/...), щоб скористалися інші; - ще краще - запропонувати PR у саму бібліотеку з типами або JSDoc-анотаціями (TypeScript уміє генерувати
.d.tsз JavaScript з JSDoc); - перевіряти, чи не з'явилися власні типи в новій версії пакета: тоді локальні декларації треба видалити, бо вони перекриватимуть справжні.