1. Background

Expect to use the global event bus in the project vUE + TS. Add the event bus to the vUE prototype as follows:

Vue.prototype.$bus = new Vue(); 
Copy the code

To access the event bus from within the component,

This. $bus. $emit (' start - up, params) or enclosing $bus. $on (' start - up, () = > {... })Copy the code

Here this is an instance of Vue, since the prototype of vue has the $bus attribute. Therefore, all prototype-based VUE instances should also have access to the event bus. In theory, but in practice. The error message is as follows:

TS2339: Property '$bus' does not exist on type 'Vue'.
Copy the code

2. Error causes are reported

The compiler detects that the $bus attribute does not exist on the Vue object. For the compiler, the presence of the $bus attribute depends on whether the $bus attribute is explicitly defined on the Vue’s type declaration. Further, the compiler will report an error if attributes not defined in the vue.d. ts file are referenced on a Vue instance. Here is a look at the contents of the vue.d. ts file.

export interface Vue {
  // attributes
  readonly $el: Element;
  readonly $options: ComponentOptions<Vue>;
  readonly $parent: Vue;
  readonly $root: Vue;
  readonly $children: Vue[];
  readonly $refs: { [key: string]: Vue | Element | Vue[] | Element[] };
  readonly $slots: { [key: string]: VNode[] | undefined };
  readonly $scopedSlots: { [key: string]: NormalizedScopedSlot | undefined };
  readonly $isServer: boolean;
  readonly $data: Record<string, any>;
  readonly $props: Record<string, any>;
  readonly $ssrContext: any;
  readonly $vnode: VNode;
  readonly $attrs: Record<string, string>;
  readonly $listeners: Record<string, Function | Function[]>;
  // operations
  ...
}
Copy the code

As you can see, there is no $bus attribute in Vue. Therefore, you need to add them manually. But we can’t go directly to node_modules/vue/types/vue. Which s file to add. Although it cannot be modified, we can expand the vue.d.ts file.

2. Practice

  • Create a new Typings directory under the project’s SRC directory.
  • Create a new vue-extend.ts file in the Typings directory.
  • Fill in the following contents in the vue-extend.ts file.
import Vue from 'vue';

declare module 'vue/types/vue' {
  interface Vue {
    readonly $bus: any
  }
}
Copy the code

3. Precautions

Don’t forget to introduce vUE in vue-extend.ts files. import Vue from ‘vue’;

4. Principle analysis

declare module 'vue/types/vue' {
  interface Vue {
    readonly $bus: any
  }
}
Copy the code

The meaning of this code is in node_modules/vue/types/vue/index which s a module, declared in a file defined in the module internal interface called vue. But there is also an interface named vue in vue/types/vue.d.ts. Interfaces with the same name are automatically merged. See the official document merge interface for details.

5. Sample code

Complete the case