LoginSignup
4

More than 3 years have passed since last update.

Nuxt TypeScript でデコレーターを使わずにミックスインする方法

Last updated at Posted at 2020-06-28

まず、普通にJavaScriptで書いた場合このようになります。

~/plugins/mixins.js
export const delayMixin = {
  methods: {
    $delay(ms): Promise {
      return new Promise((resolve) => setTimeout(resolve, ms));
    },
  },
});
Component.vue
<script>
import { delayMixin } from '~/plugins/mixins';

export default {
  mixins: [delayMixin],
  methods: {
    async animate() {
      await this.$delay(100);
      // ...
    },
  }
};
</script>

TypeScriptで書いた場合。
Vue.extendにして、Vueの型を拡張するようにします。

~/plugins/mixins.ts
import Vue from 'vue';
export const delayMixin = Vue.extend({
  methods: {
    $delay(ms: number): Promise<void> {
      return new Promise<void>((resolve) => setTimeout(resolve, ms));
    },
  },
});

Vueインスタンスの this
as InstanceType<typeof Mixinの型> として型を拡張します。

Component.vue
<script lang="ts">
import Vue from 'vue';
import { delayMixin } from '~/plugins/mixins';

export default Vue.extend({
  mixins: [delayMixin],
  methods: {
    async animate() {
      await (this as InstanceType<typeof delayMixin>).$delay(100);
      // ...
    },
  }
});
</script>

ビルド時に.vueファイルを認識してくれない場合には、以下のようなvue-shims.d.tsを用意して読み込ませます。

vue-shims.d.ts
declare module '*.vue' {
  import Vue from 'vue';
  export default Vue;
}

同じ要領で、Vueの親コンポーネントから子コンポーネントのメソッドを呼び出したいときには、以下のようにすればTypeScriptの型チェックでエラーがでなくなります。

TheParent.vue
<template>
  <div>
    <TheChild ref="childRef" />
  </div>
</template>

<script lang="ts">
import Vue from 'vue';
import TheChild from '~/components/TheChild.vue';

export default Vue.extend({
  components: {
    TheChild
  },
  methods: {
    foo() {
      (this.$refs.childRef as InstanceType<typeof TheChild>).doChildMethod();
    }
  }
});
</script>

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4