toRefs,
} from 'vue-demi'
import { StoreGetters, StoreState } from './store'
-import type { PiniaCustomStateProperties, StoreGeneric } from './types'
+import type {
+ _ActionsTree,
+ _GettersTree,
+ _UnwrapAll,
+ PiniaCustomStateProperties,
+ StateTree,
+ Store,
+ StoreGeneric,
+} from './types'
type ToComputedRefs<T> = {
[K in keyof T]: ToRef<T[K]> extends Ref<infer U>
: ToRef<T[K]>
}
+/**
+ * Extracts the refs of a state object from a store. If the state value is a Ref or type that extends ref, it will be kept as is.
+ * Otherwise, it will be converted into a Ref.
+ */
+declare type ToStateRefs<SS> =
+ SS extends Store<
+ string,
+ infer UnwrappedState,
+ _GettersTree<StateTree>,
+ _ActionsTree
+ >
+ ? UnwrappedState extends _UnwrapAll<Pick<infer State, infer Key>>
+ ? {
+ [K in Key]: ToRef<State[K]>
+ }
+ : ToRefs<UnwrappedState>
+ : ToRefs<StoreState<SS>>
+
/**
* Extracts the return type for `storeToRefs`.
* Will convert any `getters` into `ComputedRef`.
*/
-export type StoreToRefs<SS extends StoreGeneric> = ToRefs<
- StoreState<SS> & PiniaCustomStateProperties<StoreState<SS>>
-> &
+export type StoreToRefs<SS extends StoreGeneric> = ToStateRefs<SS> &
+ ToRefs<PiniaCustomStateProperties<StoreState<SS>>> &
ToComputedRefs<StoreGetters<SS>>
/**
pinia.use(({ options, store }) => {
const { debounce: debounceOptions } = options
if (debounceOptions) {
- return Object.keys(debounceOptions).reduce((debouncedActions, action) => {
- debouncedActions[action] = debounce(
- store[action],
- debounceOptions[action]
- )
- return debouncedActions
- }, {} as Record<string, (...args: any[]) => any>)
+ return Object.keys(debounceOptions).reduce(
+ (debouncedActions, action) => {
+ debouncedActions[action] = debounce(
+ store[action],
+ debounceOptions[action]
+ )
+ return debouncedActions
+ },
+ {} as Record<string, (...args: any[]) => any>
+ )
}
})
const double = computed(() => n.value * 2)
return {
n,
- double
+ double,
+ }
+ })()
+ )
+)
+
+expectType<{
+ n: Ref<number>
+ customN: Ref<number> & { plusOne: () => void }
+ double: ComputedRef<number>
+ myState: Ref<number>
+ stateOnly: Ref<number>
+}>(
+ storeToRefs(
+ defineStore('a', () => {
+ const n = ref(1)
+ const customN = ref(1) as Ref<number> & { plusOne: () => void }
+ const double = computed(() => n.value * 2)
+ return {
+ n,
+ customN,
+ double,
+ }
+ })()
+ )
+)
+
+expectType<{
+ n: Ref<number>
+ customN: Ref<number> & { plusOne: () => void }
+ double: ComputedRef<number>
+ myState: Ref<number>
+ stateOnly: Ref<number>
+}>(
+ storeToRefs(
+ defineStore('a', () => {
+ const n = ref(1)
+ const customN = ref(1) as Ref<number> & { plusOne: () => void }
+ const double = computed(() => n.value * 2)
+
+ function plusOne() {
+ customN.value++
+ }
+
+ return {
+ n,
+ customN,
+ double,
+ plusOne,
}
})()
)
)
+
+expectType<{
+ n: Ref<number>
+ customN: Ref<number> & { plusOne: () => void }
+ double: ComputedRef<number>
+ myState: Ref<number>
+ stateOnly: Ref<number>
+}>(
+ storeToRefs(
+ defineStore('a', {
+ state: () => ({
+ n: 1,
+ customN: ref(1) as Ref<number> & { plusOne: () => void },
+ }),
+ getters: {
+ double: (state) => state.n * 2,
+ },
+ actions: {
+ plusOne() {
+ this.n++
+ },
+ },
+ })()
+ )
+)
+
+expectType<{
+ n: Ref<number>
+ customN: Ref<number> & { plusOne: () => void }
+ double: ComputedRef<number>
+ myState: Ref<number>
+ stateOnly: Ref<number>
+}>(
+ storeToRefs(
+ defineStore('a', {
+ state: () => ({
+ n: 1,
+ customN: ref(1) as Ref<number> & { plusOne: () => void },
+ }),
+ getters: {
+ double: (state) => state.n * 2,
+ },
+ actions: {
+ plusOne() {
+ this.n++
+ },
+ },
+ })()
+ )
+)