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

Як доповнити типи сторонньої бібліотеки через module augmentation?

Доповнення модуля (module augmentation) додає поля до інтерфейсів, оголошених у чужому пакеті, не змінюючи сам пакет. Працює через злиття інтерфейсів.

Приклад з Vue - глобальна властивість у шаблонах:

// src/types/vue.d.ts
import type { Translator } from '../i18n';

declare module 'vue' {
  interface ComponentCustomProperties {
    $t: Translator;
  }
}

Тепер $t має тип у всіх шаблонах і this в Options API.

Приклад з Pinia - власна опція стора, з Vue Router - типізоване meta:

import 'vue-router';

declare module 'vue-router' {
  interface RouteMeta {
    requiresAuth?: boolean;
    title?: string;
  }
}

Express - поле в запиті. Типи Express оголошені в глобальному просторі імен, тому доповнюють його через declare global:

import type { User } from './models.js';

declare global {
  namespace Express {
    interface Request {
      user?: User;
    }
  }
}

Обов'язкові умови:

  1. файл має бути модулем - містити хоча б один import чи export на верхньому рівні (часто додають export {}). У файлі-скрипті declare module 'vue' замінить оголошення модуля замість доповнення - і всі типи Vue зникнуть. Це дзеркальна протилежність ситуації з declare module '*.svg', якому, навпаки, потрібен скрипт;
  2. назва модуля має точно збігатися з тим, що імпортують ('vue', а не '@vue/runtime-core', якщо бібліотека радить саме 'vue');
  3. доповнювати можна лише існуючі інтерфейси - нові експорти чи нові модулі так не додаються;
  4. файл має потрапити в компіляцію (include у tsconfig).

Бібліотеки часто проєктують такі точки розширення навмисно: порожній інтерфейс-«реєстр», який користувач доповнює, - і всі API бібліотеки автоматично отримують точні типи (події, маршрути, теми, сховища).

Пастка: доповнення діють глобально для всієї програми. Поле, додане до Request у одному місці, видно всюди - тож тип має бути чесним (user?: User, а не user: User, якщо middleware автентифікації працює не на всіх маршрутах).

Докладніше в документації: Злиття оголошень: доповнення модуля

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