UNPKG

vuex-tstore

Version:

Provides a low-overhead TypeScript wrapper around Vuex that can trigger compilation errors and IntelliSense tips.

108 lines (103 loc) 3.12 kB
import { ActionContext, Store } from "vuex"; import { qualifyKey, Result } from "./util"; /** * Provides an interface for accessors from a list of getters. * * Given an object that matches the type `TGetters` (below), this type * provides an interface that matches the type `TGetAccessors` (below). * * ```typescript * interface TGetters { * [key: string | number | symbol]: ( * state?: TModuleState, * getters?: any, * rootState?: TRootState, * rootGetters?: any * ) => TResult * } * * type TGetAccessors = { * [key in keyof TGetters]: () => TResult * } * ``` */ export type GetAccessors<TModuleState, TRootState, TGetters> = { [key in keyof TGetters]: GetAccessor< TModuleState, TRootState, Result<TGetters[key]> >; }; /** * Provides an interface for wrapped getter accessors. * * Given an object that matches the type `TGetAccessors` (below), this type * reflects an interface that matches the type `TWrappedGetters` (below). * * ```typescript * interface TGetAccessors { * [key: string | number | Symbol]: () => TResult * } * * type WrappedGetters = { * [key in keyof TGetAccessors]: TResult * } * ``` */ export type WrappedGetters<TGetAccessors> = { [key in keyof TGetAccessors]: Result<TGetAccessors[key]>; }; /** * Represents a function that gets the value of a Vuex getter. */ type GetAccessor<TModuleState, TRootState, TResult> = ( store: Store<TRootState> | ActionContext<TModuleState, TRootState> ) => TResult; /** * Converts a dictionary of GetAccessors into a WrappedGetters implementation. * * This looks like a scary way to handle this, but it works. I'm explicitly * choosing to bypass the type system to tell the compiler "trust me, this * does what we expect it to do" in order to avoid having to make an already * complex type system *even more* complex. Basically, we're creating a wrapper * around the getters so that they don't need to reference the store all * the time. * * @param store Provides a reference to the store to execute getters against. * @param getters Provides a reference to the getter definitions to create wrappers around. * * ```typescript * import { Store } from 'vuex'; * import { wrapGetters } from 'vuex-tstore'; * * const options = { * getters: { * foo(state) { return 'bar'; }, * hello(state) { return (name: string) => `Hello, ${name}`; }, * }, * }; * * const store = new Store(options); * const getters = wrapGetters(store, options.getters); * * getters.foo; // 'bar' * getters.hello('world'); // 'Hello, world' * ``` */ export function wrapGetters< TModuleState, TRootState, TGetters extends object, TGetAccessors = GetAccessors<TModuleState, TRootState, TGetters>, TWrappedGetters = WrappedGetters<TGetAccessors> >( namespace: string, store: Store<TRootState>, options: TGetAccessors ): TWrappedGetters { return Object.entries(options).reduce((getters, [key, getter]) => { return Object.defineProperty(getters, key, { get: () => store.getters[qualifyKey(getter, namespace)] }); }, {}) as TWrappedGetters; }