Subscribe on changes!

Access global properties in grandchild components raises typescript error

avatar
Sep 23rd 2020

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; }'

avatar
Sep 24th 2020

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

avatar
Sep 24th 2020

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

avatar
Sep 24th 2020

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

avatar
Nov 19th 2020

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.

avatar
Nov 19th 2020

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

avatar
Dec 1st 2020

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

avatar
Dec 1st 2020

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

avatar
Dec 1st 2020

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.

avatar
Aug 19th 2021

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.

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.

You said it in the official document, How to write a separate file? thanks

avatar
Aug 19th 2021

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.

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.

You said it in the official document, How to write a separate file? thanks


Chinese

为了让 TypeScript 能够加载这个文件,你需要让 TypeScript 能识别到这个文件,也就是说,这个文件的位置要位于 tsconfig.json 配置项的 include 里。

根据 TypeScript 的配置文件,如果不加这个选项(也就是使用默认值),你只需要把它放在 src 目录里就可以,如果要放在其他的地方,就得配置一下,让 TypeScript 能找到它。


English

In order for TypeScript to load this file, you need to make TypeScript recognize this file, so, the address of this file must be located in the include of the tsconfig.json configuration item.

According to TypeScript configuration file, if this option is not added (the default value is used), you only need to put it in the src directory. , If you want to put it in other places, you have to configure it so that TypeScript can find it.