'Add global properties to Vue 3 using TypeScript
I want to add a global property to a Vue 3 application like suggested here
The prototype approach does not work with TypeScript.
I found an example that I converted into this code as config.d.ts
import Vue from 'vue'
import base from '@/config/config.json'
import dev from '@/config/config.dev.json'
import prod from '@/config/config.prod.json'
let config
if (process.env.NODE_ENV === 'production') {
config = Object.freeze(Object.assign(base, prod))
} else {
config = Object.freeze(Object.assign(base, dev))
}
declare module 'vue/types/vue' {
interface Vue {
$config: config
}
}
I want to load some local configuration files with dev or prod scope. The scoped files will not be checked into GIT repository.
The main.ts now looks like this...
import Vue from 'vue'
import {createApp} from 'vue'
import App from './App.vue'
import Config from '@/plugins/config.d.ts'
Vue.use(Config)
createApp(App).mount('#app')
The problem:
ERROR in src/main.ts:6:5
TS2339: Property 'use' does not exist on type 'typeof import("d:/Martin/Entwicklung/2020/STA-Electron/node_modules/vue/dist/vue")'.
4 | import Config from '@/plugins/config.d.ts'
5 |
> 6 | Vue.use(Config)
| ^^^
7 | createApp(App).mount('#app')
8 |
What I ideally want to achieve is a global config or $config property that can be used in the setup method of Vue 3
export default defineComponent({
name: 'App',
components: {},
setup(props, context) {
const elem = ref(context.$config.prop1)
const doSth = () => {
console.log('Config', context.$config)
}
return {doSth, elem}
},
})
How can I fix this?
Update
After the answer from danielv so new plugin looks this
import {App} from 'vue'
export interface ConfigOptions {
base: any
dev: any
prod: any
}
export default {
install: (app: App, options: ConfigOptions) => {
app.config.globalProperties.$config =
process.env.NODE_ENV === 'production'
? Object.freeze(Object.assign({}, options.base, options.prod))
: Object.freeze(Object.assign({}, options.base, options.dev))
},
}
The main.ts changed also into this
import {createApp} from 'vue'
import App from '@/App.vue'
import ConfigPlugin from '@/plugins/config'
import base from '@/config/config.json'
import dev from '@/config/config.dev.json'
import prod from '@/config/config.prod.json'
createApp(App).use(ConfigPlugin, {base, dev, prod}).mount('#app')
This simple plugin can be used in the template
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<p>{{ $config.prop1 }}</p>
</template>
IntelliJ complains about unknown variable prop1, but it works.
I searched a lot but found no way to insert my $config into the setup method that is used with the composition api.
Solution 1:[1]
You can augment the @vue/runtime-core TypeScript module in your application:
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$config: Record<string, unknown>;
}
}
export {} // Important! See note.
Here is a documentation: ComponentCustomProperties
Important note: TS module augmentation works correctly only when it is placed in the module.
In TypeScript, just as in ECMAScript 2015, any file containing a top-level
importorexportis considered a module. Conversely, a file without any top-levelimportorexportdeclarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).
Therefore the file must contain at least one top-level import or export statement, even if empty one (as in the example above) - Type Augmentation Placement
Solution 2:[2]
In Vue 3, you call the use method on the instance of your app, it's not a method on the Vue var.
const app = createApp(App)
app.mount('#app')
app.use(config)
Also, you need to write your plugin to conform to what Vue 3 expects (an object with install method).
Check out Vue 3 guide on writing and using plugins, it describe a very similar use case to yours.
By the way, *.d.ts files are intended to be used as pure declaration files to declare types, usually as a supplement to otherwise untyped modules (e.g. typing existing js code). You generally don't need to write *.d.ts files yourself when writing Typescript code (declarations can be auto generated by the tsc compiler).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Michal Levý |
| Solution 2 | danielv |
