JavaScript での Vuex にて getters や actions などの定義で state を推論して中身を確認しながら実装する

# JavaScript でも Vuex 定義時に推論をしたい

TypeScript の場合は [Vuex and Typescript - codeburst](https://codeburst.io/vuex-and-typescript-3427ba78cfa8) などをさんこうにしましょう
JavaScript で TypeScript のような推論を行う事例として

* 上記の [Vuex and Typescript](https://codeburst.io/vuex-and-typescript-3427ba78cfa8) と
* [Type Safe JavaScript with JSDoc - TruckJS - Medium](https://medium.com/@trukrs/type-safe-javascript-with-jsdoc-7a2a63209b76) との組み合わせにておこないます

[モジュールモードですぐに Vuex の store が使用できる Nuxt.js](https://ja.nuxtjs.org/guide/vuex-store) にてやります

## state の定義

[Vuex and Typescript](https://codeburst.io/vuex-and-typescript-3427ba78cfa8) では `ProfileState`, `RootState` をそれぞれ定義しています。
Vuex の Getter や Action が `<S, R>` などとしてもとめているからです

### RootState にあたるもの

「中身」の `State` も `export` 対象にしているところがポイントです
[Vuex and Typescript](https://codeburst.io/vuex-and-typescript-3427ba78cfa8) にて定義されている `interface RootState` の代わりとかんがえてください
`State` と `state` でわかりずらいかもしれないのでこの変数定義はあんまりよくないかもしれません

```js:store/index.js
export const State = {
  'ba-john': 'ichi'
}

export const state = () => Object.assign({}, State)
```

### ProfileState と同じ位置づけのもの

モジュールモードなので `export default` で定義したら勝手にモジュールになります
こっちも `State` を定義して `export` 対象としています

```js:store/profile/state.js
/**
 * @typedef {Object} State
 * @property {string} namae なまえ
 */

/** @type {State} */
export const State = {
  namae: 'ichi'
}

export default () => Object.assign({}, State)
```

## getters 定義

getters の定義の際には Vuex より `Getter` を `import` しましょう
さらに state で定義しておいたそれぞれの `State` をそれぞれ `import` して
getter として定義する変数に JSDoc にて `@type` を指定します。

下記の例は `State` をそれぞれ `Root` と `Local` として別名にしています

```js:store/profile/getters.js
/**
 * @typedef {import('@/store').State} RootState
 * @typedef {import('./state').State} State
 */
/** @type {import('vuex').GetterTree<State, RootState>} */
const getters = {
  getNamae: (state) => state.namae,
}
export default getters 
```

にょきにょき生えてくる state の中身

このようにして actions や mutations にも Vuex の `Action<S,R>` `Mutation<S>` に
適切な state のオブジェクトを指定することで推論がきくようになります

## mutations 定義

つごうにより actions の前に mutations を定義します

```js:store/profile/mutations.js
/**
 * @typedef {import('./state').State} State
 */

// Mutation は state, payload が明示されればよく、
// また、 MutationTree を指定してしまうと mutations のプロパティが推論できなくなるようなので
// MutationTree を指定するメリットが現状少なそう
///** @type {import('vuex').MutationTree<State>} */
const mutations = {
  /**
   * @param {State} state
   * @param {{ namae: string }} payload
   */
  setNamae: (state, payload) => {
    state.namae = payload.namae
  },
}

export default mutations
```

## actions 定義

他と同様 Vuex の Action の定義の仕方に従って `actions.js` を定義していますが・・・
同僚の `mutations` もインポートしています
これは mutations の定義を流用してその推論により `commit` をする際の参考にしております
(これは是非があるでしょうが・・・)

```js:store/profile/actions.js
/**
 * @typedef {import('@/store').State} RootState
 * @typedef {import('./state').State} State
 */
/** @type {import('vuex').ActionTree<State, RootState>} */
const actions = {
  /**
   * @param {{ namae: string }} payload
   */
  setNamae: (context, payload) => {
    // 定義名を利用して commit を実施
    context.commit(mutations.setNamae.name, payload)
  },
}
export default actions
```

Action での `context` にはいろいろと格納されているので
推論で中身がみれたほうが便利と思われます