Vuex を安全に使うための型定義
Meguro.es #13 @ ラクスル
@ktsn
Vuex?
状態とミューテーション
const store = new Vuex.Store({
// 状態
state: {
count: 0
},
// ミューテーション
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
})
// 使う側
store.commit('increment', { amount: 1 })
console.log(store.state.count) // -> 1
モジュール
// カウンターモジュール
const counter = {
namespaced: true,
state: { /* ... */ },
mutations: { /* ... */ }
}
const store = new Vuex.Store({
modules: { counter }
})
store.commit('counter/increment', { amount: 1 })
コンポーネントで使う
import Vue from 'vue'
import { mapState, mapMutations } from 'vuex'
export default Vue.extend({
// increment を this に生やす
methods: mapMutations(['increment']),
// count を this に生やす
computed: mapState(['count']),
created () {
// ミューテーション
this.increment({ amount: 1 })
// 状態
console.log(this.count)
}
})
型付けがつらい
const store = new Vuex.Store({
/* ... */
mutations: {
increment (state, payload: { amount: number }) {
state.count += payload.amount
}
}
})
// 有効な mutation 名がわからない
// payload の型がわからない
store.commit('increment', 123)
namespace の型付けが困難
定義するとき
increment (state, payload) { ... }
呼び出すとき
commit('counter/increment', payload)
無理では?
ゼロから型付けできる API で作ったほうが良い
試しに書いてみたら意外にできた
// 状態: 普通に状態の型を定義
interface CounterState {
count: number
}
// ミューテーション
// キー: ミューテーション名
// 値: ペイロードの型
interface CounterMutations {
increment: { amount: number }
}
まず状態とミューテーションの
インターフェースを定義
DefineModule
import { DefineModule } from 'vuex'
// モジュールの型注釈に DefineModule を指定
const counter: DefineModule<CounterState, {}, CounterMutations, {}> = {
// namespace 付けても良い
namespaced: true,
state: {
count: 0
},
mutations: {
// 型注釈付けなくても全部型がついてる
increment (state, payload) {
state.count += payload.amount
}
}
}
createNamespacedHelpers
import { createNamespacedHelpers } from 'vuex'
// 型パラメーターに状態、ミューテーションのインターフェースを渡す
// 引数には実際の namespace の値を渡す
export const counterHelpers
= createNamespacedHelpers<CounterState, {}, CounterMutations, {}>('counter')
// コンポーネント内でヘルパーを使う
export default Vue.extend({
methods: counterHelpers.mapMutations([
'increment' // 名前が正しいかチェックされる!
]),
created () {
// ちゃんと型付けされる!
this.increment({ amount: 1 })
}
})
型安全バンザイ 🎉
Vuex を安全に使うための型定義 #meguroes
By katashin
Vuex を安全に使うための型定義 #meguroes
- 3,203