Плагіни й app.config.globalProperties додають властивості, доступні в кожному компоненті ($t для перекладів, route() від Ziggy в Laravel-проєктах). Глобально зареєстровані компоненти (app.component('Icon', Icon)) доступні в усіх шаблонах без імпорту. TypeScript про них нічого не знає, поки їх не оголосити.
Глобальні властивості - розширення модуля vue:
// types/vue.d.ts
import type { route as routeFn } from 'ziggy-js'
export {}
declare module 'vue' {
interface ComponentCustomProperties {
route: typeof routeFn
$t: (key: string, params?: Record<string, unknown>) => string
}
}
Тепер у шаблоні {{ route('posts.show', post.id) }} і $t('cart.empty') мають типи, а друкарська помилка в назві - помилка vue-tsc.
Глобальні компоненти:
declare module 'vue' {
interface GlobalComponents {
Icon: typeof import('./components/Icon.vue')['default']
Link: typeof import('@inertiajs/vue3')['Link']
}
}
Розширення Vue - Official і vue-tsc перевіряють props таких компонентів у шаблонах так само, як імпортованих.
Важливі деталі:
- файл оголошень має бути модулем (
export {}чи будь-який імпорт/експорт), інакшеdeclare module 'vue'замінить типи Vue замість розширення; - файл має потрапити в
includeуtsconfig; - бібліотеки (Vue Router, Pinia, Inertia) самі постачають такі розширення -
$route,$routerтипізовані без ваших зусиль.
Краще уникати глобальних властивостей у Composition API. У <script setup> доступ до них через getCurrentInstance() - незручний і крихкий. Явний імпорт чи composable (const { t } = useI18n()) зрозуміліший, краще працює з tree shaking і тестами: у тесті достатньо замокати модуль, а не налаштовувати глобальні властивості.
Глобальні компоненти теж мають ціну: збирач не знає, чи вони використовуються, тож не може їх викинути чи винести в окрему частину. Реєструвати глобально варто лише справді повсюдні (іконка, посилання), решту - імпортувати там, де потрібні.
Докладніше в документації: TypeScript: розширення глобальних властивостей