Three years ago – time files – I wrote a hack to remove the boilerplate fields from a Pinia store. It worked well.
This morning, writing work stuff, I wrote a lightweight wrapper to Pinia’s defineStore
, with the primary intent to remove the manual string ID which needs to be given. After the initial TypeScript brouhaha, it went so well that I was able to fully integrate the boilerplate strip with Omit
, which is a solution even less intrusive than the one I wroten 3 years ago.
import {_ActionsTree, _GettersTree, defineStore, DefineStoreOptions, Pinia, StateTree, Store, StoreGeneric} from 'pinia';
let nStore = 0;
type LeanStoreDef<Id extends string = string, S extends StateTree = StateTree, G = _GettersTree<S>, A = _ActionsTree> = {
(pinia?: Pinia | null | undefined, hot?: StoreGeneric): Omit<Store<Id, S, G, A>,
'$id' | '$dispose' | '$onAction' | '$patch' | '$reset' | '$state' | '$subscribe' | '_customProperties'>;
$id: Id;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
export function newStore<Id extends string, S extends StateTree = {}, G extends _GettersTree<S> = {}, A = {}>(
options: Omit<DefineStoreOptions<Id, S, G, A>, 'id'>,
): LeanStoreDef<Id, S, G, A> {
return defineStore(('siorg-store-' + ++nStore) as Id, options);
}
Usage is just exactly what I had in mind:
const useNames = newStore({
state: () => ({
names: [] as string[],
}),
getters: {
count: state => state.names.length,
},
actions: {
add(name: string): void {
this.names.push(name);
},
},
});