👌

frourioでnuxt-typed-vuexを使う

2020/12/17に公開

nuxt-typed-vuexとは

vuexに型指定をするためのライブラリ。
Options APIで使える。
Class APIを選択したときははvuex-module-decoratorsを使うと良い。

frourioでフロントのフレームワークにnuxtを選択し、vuexを使おうとしたらコンポーネントからの呼び出し時にインテリセンスが効かず辛いのでnuxt-typed-vuexを入れる

導入

nuxt-typed-vuexをインストール

npm i nuxt-typed-vuex

nuxt.config.jsに下記を追加

buildModules: [
  'nuxt-typed-vuex'
],

frourioのデフォルトのテンプレートをnuxt-typed-vuexを使って書き換えてみる

store/index.ts

import {
  getAccessorType,
  getterTree,
  mutationTree,
  actionTree
} from 'typed-vuex'
import * as task from './task'

export const state = () => ({})

export const getters = getterTree(state, {})

export const mutations = mutationTree(state, {})

export const actions = actionTree({ state, getters, mutations }, {})

export const accessorType = getAccessorType({
  state,
  getters,
  mutations,
  actions,
  modules: {
    task
  }
})

types/index.d.ts

import { accessorType } from '~/store'

declare module 'vue/types/vue' {
  interface Vue {
    $accessor: typeof accessorType
  }
}

declare module '@nuxt/types' {
  interface NuxtAppOptions {
    $accessor: typeof accessorType
  }
}

store/task.ts

/* eslint-disable @typescript-eslint/no-unused-vars */
import { mutationTree, actionTree } from 'typed-vuex'
import { Task } from '$prisma/client'

export const state = () => ({
  tasks: [] as Task[]
})

export type RootState = ReturnType<typeof state>

export const mutations = mutationTree(state, {
  setTask(state, value: Task[]) {
    state.tasks = value
  }
})

export const actions = actionTree(
  { state, mutations },
  {
    async fetchTasks({ commit }) {
      const res = await this.$api.tasks.$get()
      commit('setTask', res)
    },
    async createTask({ commit }, newLabel: string) {
      if (!newLabel) return
      await this.$api.tasks.post({ body: { label: newLabel } })
    },
    async toggleDone({ commit }, task: Task) {
      await this.$api.tasks
        ._taskId(task.id)
        .patch({ body: { done: !task.done } })
    },
    async deleteTask({ commit }, task: Task) {
      await this.$api.tasks._taskId(task.id).delete()
    }
  }
)

コンポーネントからの呼び出し

this.$accessorを使ってstoreにアクセスする

pages/index.vue

export default Vue.extend({
  data() {
    return {
      newLabel: ''
    }
  },
  async fetch() {
    await this.fetchTasks()
  },
  computed: {
    tasks() {
      return this.$accessor.task.tasks
    }
  },
  methods: {
    fetchTasks() {
      this.$accessor.task.fetchTasks()
    },
    async createTask() {
      await this.$accessor.task.createTask(this.newLabel)
      this.newLabel = ''
      this.fetchTasks()
    },
    async toggleDone(task: Task) {
      await this.$accessor.task.toggleDone(task)
      this.fetchTasks()
    },
    async deleteTask(task: Task) {
      await this.$accessor.task.deleteTask(task)
      this.fetchTasks()
    }
  }
})

インテリセンスが効き、間違った引数を設定したらエラーが出るようになった!

$accessorでstoreにアクセスしない場合、actionsを呼ぶときdispatchを使う必要があり、インテリセンスが効かない😢(もちろん型も見てくれない)

ソースコードはこちら
https://github.com/an-0305/frourio-nuxt-app/tree/develop

Discussion