Splitting Stores
Pinia Generic has 3 functions to define the state, getters and actions of a store independently.
createState()
createGetters()
createActions()
Simple store
PiniaStore<>
type
First we create a type for the store. This will be used to type the this
parameter in the getters and actions.
import type { PiniaStore } from 'pinia-generic'
type CategoryStore = PiniaStore<
'category',
{
id: number
name: string
},
{
getId: () => number
getName: () => string
}
>
The PiniaStore<>
type takes 5 optional generic parameters:
- The name of the store (this is the id passed to
defineStore()
) - State
- Getters
- Actions
- Generic store to extend
Note: this is a wrapper around the
Store<>
type from Pinia, with the last Generic store parameter, so if you are just splitting your stores, you can use theStore<>
type directly.
You can of course split this type up too.
interface CategoryState { // or call it Category if it's an existing type
id: number
name: string
}
// ...
type CategoryStore = Store<
'category',
CategoryState,
CategoryGetters,
>
WARNING
Here we only have a state and getters, showing how the generic parameters are optional.
Optional generic types cannot be skipped though, so you will need to pass an empty object: {}
.
type CategoryStore = Store<
'category',
CategoryState,
object,
CategoryActions,
>
State and getters
Then we implement the state and the getters.
createState()
, createGetters()
and createActions()
are generic functions that take the store type as a parameter, and return the state and getters objects.
import { createGetters, createState } from 'pinia-generic'
const state = createState<CategoryStore>({
id: 0,
name: 'Hi',
})
const getters = createGetters<CategoryStore>({
getId() {
return this.id
},
getName() {
return this.name
},
})
NOTE
The whole point of this package is to properly type the this
parameter, and the object passed to the create
functions. If you misspell a property, or forget to add it, you will get a type error.
Because we are passing the CategoryStore
type to the create
functions, the state and getters objects are entirely independent from each other, so you can put them in separate files.
It's all coming together
Finally, we export and import them, and create the store.
import { defineStore } from 'pinia'
import { state } from './state'
import { getters } from './getters'
export const useCategoryStore = defineStore('category', {
state: () => state,
getters,
})
Note: the state needs to be an arrow function for
defineStore()
.
We only worked on top of Pinia, so the store can be used like any other.
const category = useCategoryStore()
const id = category.getId
category.name = 'Hello'