How can I use mixin with vue-class-component and typescript?

I am currently working on a shared data service, planing to use mixin.

//data.service.ts
// ...
@Component({})
export default class DataService extends Vue{
  mixinsData = '123'
}

And it is imported into my App.vue:

// App.vue
// ...
import DataService from './mixins/data.service'; // <-- BOOM!
// ...
@Component({
  name: 'app',
  mixins: [DataService]
})
export default class App extends Vue {
  mixins: [DataService];
  // ...
}

(Now the editor will warn me

File ‘…/mixins/data.service.ts’ is not a module.

)

I ignored that because in fact the compilation will have been successful so far.

I’d like to get access to that mixinsData as a plain Javascript file does

  created() {
    console.log(this.mixinsData); // <-- BOOM!
  }

but now it beaks, as typescript compiler will complain about:

Property ‘mixinsData’ does not exist on type ‘App’.

Q: How can I use mixin with vue-class-component and typescript?

Thanks for your help.

I’m using Typescript, this does not seem working. :pensive: @ktsn

This is because ts cannot recognize mixins options to extend your component type.
You need to extend the component type manually.

// App.vue

import DataService from './mixins/data.service';

@Component({
  name: 'app',
  mixins: [DataService]
})
export default class App extends Vue implements DataService {
  mixinsData: string
}
2 Likes

Thank you! That works.

But do I have to register every single property from data.service.ts in App class?

Because if i don’t, ts compiler will complain about:

TS2420: Class ‘App’ incorrectly implements interface ‘DataService’.
Property ‘anotherProperty1’ is missing in type ‘App’.

As the mixin keeps expanding, there will be a lot of properties in there.

Besides, if I plan to import multiple mixins, the App class may look like a mess.

How could I handle this?:no_mouth:

Currently, vue-class-component does not have such feature. Maybe you should open a feature request to vue-class-component repo!

create the test-mixin.ts file
import {Component, Vue} from ‘vue-property-decorator’;
declare module ‘vue/types/vue’{
interface Vue{
testName:string;
testMethod(abc:string):string;
}
}
@Component
export default class TestMixin extends Vue{
testName:string=‘ABCDEFG’;
testMethod(abc:string){
console.log(‘test mixin method’,abc);
return ‘abcdefg’;
}
}

import and use it in your .vue file
import TestMixin from ‘…/mixins/test-mixin’;
@Component({
mixins:[TestMixin]
})
export default class App extends Vue {
mounted() {
console.log(this.testMethod(‘1234’));
}
}

1 Like

Thank you! It’s very helpful!

vue-class-component, and vue-property-decorator now support mixins and typescript inheritance, thus making specific module declarations unnecessary.

import { Component, Mixins, Vue } from 'vue-property-decorator';

@Component
class MyMixin extends Vue {
  public mixinData = 'foo';
}

@Component
class MyComponent extends Mixins(MyMixin) {
  public mounted() {
    console.log(this.mixinData); // Should be picked up by typescript now
  }
}
8 Likes

Wonderful news. I was about to give up on this