主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ
書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。
2018/10/02
Vuex で Firebase を良い感じに扱えるようにしてくれる VuexFire と、
TypeScript で Vuex モジュールを良い感じにかけるようにしてくれる Vue Type Helper 、
それぞれを同時に使って、型チェックや保管が効く状態で扱いたかった。
通常通り書くならこんな感じで、型チェックが効かないだけではなく、失敗する。
interface ISomeActions {
someAction: { param: string[] };
}
const actions = DefineActions<ISomeActions, ISomeState, ISomeMutations, ISomeGetters> = {
someAction: firestoreAction(async ({ bindFirebaseRef }, { param }) => {
// ...
}),
};
そこで、書き方と VuexFire の型定義を少し工夫して、型チェックや補完が効くようにする。
まずは VuexFire の型定義から。
declare module "vuexfire" {
import { ActionContext } from "vuex-type-helper";
type Fn<C, K> = (ctx: C, payload: K) => void | Promise<any>;
function firebaseAction<C extends ActionContext<any, any, any, any>, K>(func: Fn<C, K>): Fn<C, K>;
const firebaseMutations: {};
export {
firebaseAction,
firebaseMutations
};
}
必要なのは firebaseAction
と firebaseMutations
のみなので、それらを export しておく。
次に Vuex Type Helper の型定義を拡張する。
import { firestore } from "firebase";
import { ActionContext as BaseActionContext } from "vuex";
import * as vth from "vuex-type-helper";
declare module "vuex-type-helper" {
interface BindOptions {
maxRefDepth?: number;
}
export interface ActionContext<State, Getters, Actions, Mutations> extends BaseActionContext<State, any> {
bindFirebaseRef: (key: string, ref: firestore.Query, options?: BindOptions) => Promise<void>;
unbindFirebaseRef: (key: string) => void;
}
}
ActionContext
を拡張することで、 VuexFire で追加されたものについても補完が効く。
最後に、実際に Action を書く。
const actions: DefineActions<
ISomeActions,
ISomeState,
ISomeMutations,
ISomeGetters
> = {
async someAction(ctx, payload) {
firebaseAction<typeof ctx, typeof payload>(
async ({ bindFirebaseRef }, { param }) => {
// ...
}
)(ctx, payload);
},
};
型パラメータを指定しているのは、現時点ではこの書き方だと推論がうまく動いていないから。
戻り値から推論で切るみたいだけど、現状 ActionContext<{}, {}, {}, {}>
になってしまう。
もっと良い書き方が出来るかもしれないけど、私にはこれが限界だった。
ではでは (๑╹ᆺ╹)