Vue-next: Access global properties in grandchild components raises typescript error

Created on 24 Sep 2020  Â·  8Comments  Â·  Source: vuejs/vue-next

Version

3.0.0

Reproduction link

https://codesandbox.io/s/nameless-hooks-znzuv?file=/src/HelloWorld.ts

Steps to reproduce

I defined a global property called foousing app.config.globalProperties.foo = 'bar' in App instance and use it inside a child component

What is expected?

logging the foo property inside the child component without errors

What is actually happening?

I get the following error :

Property 'foo' does not exist on type '{ name: string; mounted(): void; template: string; }'

Most helpful comment

Hello, I realized a similar problem, and then tried to come to GitHub Issue to find a solution. I found it here, but it was not resolved. Finally, I figured out a way to solve this problem by myself, which is to customize the declaration file through the module augmentation of TS.

For your scene, the solution should look like this:

declare module '@vue/runtime-core' {
    export interface ComponentCustomProperties {
        emitter: typeof emitter
    }
}

Insert this code into any place in the project that could be read by TypeScript (recommended in main.js), and you can get the type of this.emitter in any component.

Similarly, global properties accessed in any other component instance can be defined in this way.

All 8 comments

You should use the defineComponent: https://v3.vuejs.org/api/global-api.html#definecomponent

You need to use defineComponent as suggested, in order to get the correct typing inference

Thank you for interacting with my issue, originally i had the issue in the following example :

main.ts

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './styles/app.scss'
import mitt from 'mitt';
const emitter = mitt();


let app=createApp(App)
app.config.globalProperties.emitter = emitter
app.use(store).use(router).mount('#app')

Sidebar.vue :

<template>
<aside class="sidebar ve-sidebar" :class="{'ve-sidebar--collapsed':!isOpen,'sidebar--collapsed':!isOpen}">
    <h1 class="ve-logo">{{isOpen?'VUEYE':'V'}}</h1>
    <Dashboard24 />

</aside>
</template>

<script lang="ts">
import {
    defineComponent
} from "vue";
// @ts-ignore
import Dashboard24 from '@carbon/icons-vue/es/dashboard/16'
export default defineComponent({
    name: "sidebar",
    data() {
        return {
            isOpen: true
        };
    },
    components: {
        Dashboard24
    },
    mounted() {

        this.emitter.on("toggle-sidebar", isOpen => {
            console.log('-----cc-----isOpen----------')
            console.log(isOpen)
            console.log('--------------------')
            this.isOpen = isOpen;
        });
    }
});
</script>

<style>
</style>

However i was using the suggested solution:

full example

Hello, I realized a similar problem, and then tried to come to GitHub Issue to find a solution. I found it here, but it was not resolved. Finally, I figured out a way to solve this problem by myself, which is to customize the declaration file through the module augmentation of TS.

For your scene, the solution should look like this:

declare module '@vue/runtime-core' {
    export interface ComponentCustomProperties {
        emitter: typeof emitter
    }
}

Insert this code into any place in the project that could be read by TypeScript (recommended in main.js), and you can get the type of this.emitter in any component.

Similarly, global properties accessed in any other component instance can be defined in this way.

i found the solution in stackoverflow https://stackoverflow.com/a/64189046/8172857 but i forgot to add it here

Each time the type is set, the project vue needs to be restarted to recognize the type。
image

Keywords: typescript augmentation augment globalProperties componentcustomproperties

The guide to add typings is into the typings itself, into @vue/runtime-core/dist/runtime-core.d.ts
Search for ComponentCustomProperties and ComponentCustomOptions declarations and check out the TSDoc

There must be a section on the docs about this too, as that's where everybody will search by default

I agree with you, but I'm too busy to perfect the docs. If there is still no one doing this after one or two month , I will try it.

Was this page helpful?
0 / 5 - 0 ratings