]> git.ipfire.org Git - thirdparty/vuejs/pinia.git/commitdiff
fix(types): actual generic store
authorEduardo San Martin Morote <posva13@gmail.com>
Fri, 23 Jul 2021 11:14:40 +0000 (13:14 +0200)
committerEduardo San Martin Morote <posva13@gmail.com>
Fri, 23 Jul 2021 11:14:40 +0000 (13:14 +0200)
BREAKING CHANGE: The existing `Store<Id, S, G, A>` types was trying to be generic when no types were specified but failing at it. Now, `Store` without any type will default to an empty Store. This enables a stricter version of `defineStore` when any of state, getters, and actions are missing. If you were using `Store` as a type, you should now use `StoreGeneric` instead, which also replaces `GenericStore` (marked as deprecated).
```diff
-function takeAnyStore(store: Store) {}
+function takeAnyStore(store: StoreGeneric) {}
```

14 files changed:
src/createPinia.ts
src/devtools/formatting.ts
src/devtools/plugin.ts
src/hmr.ts
src/index.ts
src/mapHelpers.ts
src/rootStore.ts
src/store.ts
src/testing.ts
src/types.ts
test-dts/customizations.test-d.ts
test-dts/index.d.ts
test-dts/plugins.test-d.ts
test-dts/store.test-d.ts

index fb8ce0d63d5916e240e13a6a313ad157807e4c20..5f4bf4975547369f45a064ec4ade80cea87331ff 100644 (file)
@@ -7,7 +7,7 @@ import {
 import { ref, App, markRaw, effectScope } from 'vue'
 import { registerPiniaDevtools, devtoolsPlugin } from './devtools'
 import { IS_CLIENT } from './env'
-import { StateTree, Store } from './types'
+import { StateTree, StoreGeneric } from './types'
 
 /**
  * Creates a Pinia instance to be used by the application
@@ -52,7 +52,7 @@ export function createPinia(): Pinia {
     // @ts-expect-error
     _a: null,
     _e: scope,
-    _s: new Map<string, Store>(),
+    _s: new Map<string, StoreGeneric>(),
     state,
   })
 
index 892bbe24202f36c7fc1aed7e02203e464a4b16ad..212c79d803f35f35d66ed621f252e6e2ef4f2d84 100644 (file)
@@ -3,7 +3,7 @@ import {
   CustomInspectorNode,
   CustomInspectorState,
 } from '@vue/devtools-api'
-import { Store, MutationType } from '../types'
+import { MutationType, StoreGeneric } from '../types'
 import { DebuggerEvent } from 'vue'
 import { Pinia } from '../rootStore'
 import { isPinia } from './utils'
@@ -20,7 +20,7 @@ export const PINIA_ROOT_LABEL = '🍍 Pinia (root)'
 export const PINIA_ROOT_ID = '_root'
 
 export function formatStoreForInspectorTree(
-  store: Store | Pinia
+  store: StoreGeneric | Pinia
 ): CustomInspectorNode {
   return '$id' in store
     ? {
@@ -34,7 +34,7 @@ export function formatStoreForInspectorTree(
 }
 
 export function formatStoreForInspectorState(
-  store: Store | Pinia
+  store: StoreGeneric | Pinia
 ): CustomInspectorState {
   if (isPinia(store)) {
     const state: CustomInspectorState = {
@@ -63,7 +63,6 @@ export function formatStoreForInspectorState(
     state: Object.keys(store.$state).map((key) => ({
       editable: true,
       key,
-      // @ts-expect-error
       value: store.$state[key],
     })),
   }
@@ -73,7 +72,6 @@ export function formatStoreForInspectorState(
     state.getters = store._getters.map((getterName) => ({
       editable: false,
       key: getterName,
-      // @ts-expect-error
       value: store[getterName],
     }))
   }
@@ -82,7 +80,6 @@ export function formatStoreForInspectorState(
     state.customProperties = Array.from(store._customProperties).map((key) => ({
       editable: true,
       key,
-      // @ts-expect-error
       value: store[key],
     }))
   }
index d8d59bc7378c973025a03b1d0ccfc02074cc3a83..36333d36e44bd97b6c499532b9b3ed8e0c873552 100644 (file)
@@ -2,11 +2,11 @@ import { setupDevtoolsPlugin, TimelineEvent } from '@vue/devtools-api'
 import { App, ComponentPublicInstance, toRaw } from 'vue'
 import { Pinia, PiniaPluginContext } from '../rootStore'
 import {
-  Store,
   GettersTree,
   MutationType,
   StateTree,
   ActionsTree,
+  StoreGeneric,
 } from '../types'
 import {
   actionGlobalCopyState,
@@ -130,7 +130,6 @@ export function registerPiniaDevtools(app: App, pinia: Pinia) {
                 key: 'getters',
                 editable: false,
                 value: store._getters.reduce((getters, key) => {
-                  // @ts-expect-error
                   getters[key] = store[key]
                   return getters
                 }, {} as GettersTree<StateTree>),
@@ -142,7 +141,7 @@ export function registerPiniaDevtools(app: App, pinia: Pinia) {
 
       api.on.getInspectorTree((payload) => {
         if (payload.app === app && payload.inspectorId === INSPECTOR_ID) {
-          let stores: Array<Store | Pinia> = [pinia]
+          let stores: Array<StoreGeneric | Pinia> = [pinia]
           stores = stores.concat(Array.from(pinia._s.values()))
 
           payload.rootNodes = (
@@ -239,7 +238,7 @@ export function registerPiniaDevtools(app: App, pinia: Pinia) {
   )
 }
 
-function addStoreToDevtools(app: App, store: Store) {
+function addStoreToDevtools(app: App, store: StoreGeneric) {
   if (!componentStateTypes.includes(getStoreType(store.$id))) {
     componentStateTypes.push(getStoreType(store.$id))
   }
@@ -370,17 +369,15 @@ let activeAction: number | undefined
  * @param store - store to patch
  * @param actionNames - list of actionst to patch
  */
-function patchActionForGrouping(store: Store, actionNames: string[]) {
+function patchActionForGrouping(store: StoreGeneric, actionNames: string[]) {
   // original actions of the store as they are given by pinia. We are going to override them
   const actions = actionNames.reduce((storeActions, actionName) => {
     // use toRaw to avoid tracking #541
-    // @ts-expect-error
     storeActions[actionName] = toRaw(store)[actionName]
     return storeActions
   }, {} as ActionsTree)
 
   for (const actionName in actions) {
-    // @ts-expect-error
     store[actionName] = function () {
       // setActivePinia(store._p)
       // the running action id is incremented in a before action hook
@@ -409,7 +406,7 @@ function patchActionForGrouping(store: Store, actionNames: string[]) {
 export function devtoolsPlugin<
   Id extends string = string,
   S extends StateTree = StateTree,
-  G extends GettersTree<S> = GettersTree<S>,
+  G /* extends GettersTree<S> */ = GettersTree<S>,
   A /* extends ActionsTree */ = ActionsTree
 >({ app, store, options }: PiniaPluginContext<Id, S, G, A>) {
   // HMR module
index ab2e76d10d9de1cdc95c262bfc675449c3b34f3b..61ad82e977e35f847b847668aab9a4784278fead 100644 (file)
@@ -1,6 +1,6 @@
 import { isRef, isReactive } from 'vue'
 import { Pinia } from './rootStore'
-import { isPlainObject, Store, StoreDefinition, _Method } from './types'
+import { isPlainObject, StoreDefinition, StoreGeneric, _Method } from './types'
 
 /**
  * Checks if a function is a `StoreDefinition`
@@ -66,10 +66,7 @@ export function patchObject(
  * @param initialUseStore - return of the defineStore to hot update
  * @param hot - `import.meta.hot`
  */
-export function acceptHMRUpdate(
-  initialUseStore: StoreDefinition<string, any, any, any>,
-  hot: any
-) {
+export function acceptHMRUpdate(initialUseStore: StoreDefinition, hot: any) {
   return (newModule: any) => {
     const pinia: Pinia | undefined = hot.data.pinia || initialUseStore._pinia
 
@@ -97,7 +94,7 @@ export function acceptHMRUpdate(
           return hot.invalidate()
         }
 
-        const existingStore: Store = pinia._s.get(id)!
+        const existingStore: StoreGeneric = pinia._s.get(id)!
         if (!existingStore) {
           console.log(`skipping hmr because store doesn't exist yet`)
           return
index bf7b29fd369f5e4caf6d6d657c6f76d024dcf2cb..7b801247c6a4ed9c539c2a91b3107ab80b532215 100644 (file)
@@ -7,6 +7,7 @@ export { defineStore } from './store'
 export type {
   StateTree,
   Store,
+  StoreGeneric,
   GenericStore,
   StoreDefinition,
   StoreWithGetters,
index 7d4a5eba11dacc934c89eb5883946bb3527c617f..43f2468092b292051c2d925d7b6ef6e1d4321989 100644 (file)
@@ -146,7 +146,7 @@ export type _MapStateObjectReturn<
     keyof S | keyof G | ((store: Store<Id, S, G, A>) => any)
   >
 > = {
-  [key in keyof T]: () => T[key] extends (store: Store) => infer R
+  [key in keyof T]: () => T[key] extends (store: any) => infer R
     ? R
     : T[key] extends keyof Store<Id, S, G, A>
     ? Store<Id, S, G, A>[T[key]]
@@ -260,7 +260,6 @@ export function mapState<
   return Array.isArray(keysOrMapper)
     ? keysOrMapper.reduce((reduced, key) => {
         reduced[key] = function (this: ComponentPublicInstance) {
-          // @ts-expect-error
           return useStore(this.$pinia)[key]
         } as () => any
         return reduced
@@ -392,8 +391,7 @@ export function mapActions<
           this: ComponentPublicInstance,
           ...args: any[]
         ) {
-          // @ts-expect-error
-          return (useStore(this.$pinia)[key] as _Method)(...args)
+          return useStore(this.$pinia)[key](...args)
         }
         return reduced
       }, {} as _MapActionsReturn<A>)
@@ -403,7 +401,6 @@ export function mapActions<
           this: ComponentPublicInstance,
           ...args: any[]
         ) {
-          // @ts-expect-error
           return useStore(this.$pinia)[keysOrMapper[key]](...args)
         }
         return reduced
@@ -491,12 +488,10 @@ export function mapWritableState<
         // @ts-ignore
         reduced[key] = {
           get(this: ComponentPublicInstance) {
-            // @ts-expect-error
             return useStore(this.$pinia)[key]
           },
           set(this: ComponentPublicInstance, value) {
             // it's easier to type it here as any
-            // @ts-expect-error
             return (useStore(this.$pinia)[key] = value as any)
           },
         }
@@ -506,12 +501,10 @@ export function mapWritableState<
         // @ts-ignore
         reduced[key] = {
           get(this: ComponentPublicInstance) {
-            // @ts-expect-error
             return useStore(this.$pinia)[keysOrMapper[key]]
           },
           set(this: ComponentPublicInstance, value) {
             // it's easier to type it here as any
-            // @ts-expect-error
             return (useStore(this.$pinia)[keysOrMapper[key]] = value as any)
           },
         }
index 955dcda00a0325f979d16e764c8ec226193ae3ca..9b3eaa5aa2709813f47439e053a99a7e5a471327 100644 (file)
@@ -1,16 +1,14 @@
 import { App, EffectScope, InjectionKey, Plugin, Ref, warn } from 'vue'
 import {
   StateTree,
-  StoreWithState,
-  StateDescriptor,
   PiniaCustomProperties,
   _Method,
   Store,
   GettersTree,
   ActionsTree,
   PiniaCustomStateProperties,
-  GenericStore,
   DefineStoreOptionsInPlugin,
+  StoreGeneric,
 } from './types'
 
 /**
@@ -44,23 +42,6 @@ export const getActivePinia = () => {
   return activePinia!
 }
 
-/**
- * Map of stores based on a Pinia instance. Allows setting and retrieving stores
- * for the current running application (with its pinia).
- */
-
-export const storesMap = new WeakMap<
-  Pinia,
-  Map<
-    string,
-    [
-      StoreWithState<string, StateTree>,
-      StateDescriptor<StateTree>,
-      InjectionKey<Store>
-    ]
-  >
->()
-
 /**
  * Every application must own its own pinia to be able to create stores
  */
@@ -105,7 +86,7 @@ export interface Pinia {
    *
    * @internal
    */
-  _s: Map<string, GenericStore>
+  _s: Map<string, StoreGeneric>
 
   /**
    * Added by `createTestingPinia()` to bypass `useStore(pinia)`.
@@ -128,7 +109,7 @@ declare module '@vue/runtime-core' {
      *
      * @internal
      */
-    _pStores?: Record<string, Store>
+    _pStores?: Record<string, StoreGeneric>
   }
 }
 
@@ -142,7 +123,7 @@ export const piniaSymbol = (
 export interface PiniaPluginContext<
   Id extends string = string,
   S extends StateTree = StateTree,
-  G extends GettersTree<S> = GettersTree<S>,
+  G /* extends GettersTree<S> */ = GettersTree<S>,
   A /* extends ActionsTree */ = ActionsTree
 > {
   /**
index 5e6e219bd1d6426ce4a2a3a0d77231ba1a109ddf..14d324d7c8ab810455b3256efc25cb60fffb576c 100644 (file)
@@ -35,6 +35,7 @@ import {
   _UnionToTuple,
   DefineSetupStoreOptions,
   DefineStoreOptionsInPlugin,
+  StoreGeneric,
 } from './types'
 import {
   getActivePinia,
@@ -435,9 +436,7 @@ function createSetupStore<
     store._hotUpdate = markRaw((newStore) => {
       newStore._hmrPayload.state.forEach((stateKey) => {
         if (stateKey in store.$state) {
-          // @ts-expect-error
           const newStateTarget = newStore.$state[stateKey]
-          // @ts-expect-error
           const oldStateSource = store.$state[stateKey]
           if (
             typeof newStateTarget === 'object' &&
@@ -446,7 +445,6 @@ function createSetupStore<
           ) {
             patchObject(newStateTarget, oldStateSource)
           } else {
-            // @ts-expect-error
             // transfer the ref
             newStore.$state[stateKey] = oldStateSource
           }
@@ -460,7 +458,6 @@ function createSetupStore<
       // remove deleted state properties
       Object.keys(store.$state).forEach((stateKey) => {
         if (!(stateKey in newStore.$state)) {
-          // @ts-expect-error
           delete store[stateKey]
         }
       })
@@ -468,9 +465,7 @@ function createSetupStore<
       pinia.state.value[$id] = toRef(newStore._hmrPayload, 'hotState')
 
       for (const actionName in newStore._hmrPayload.actions) {
-        const action: _Method =
-          // @ts-expect-error
-          newStore[actionName]
+        const action: _Method = newStore[actionName]
 
         // @ts-expect-error: new key
         store[actionName] =
@@ -496,7 +491,6 @@ function createSetupStore<
       // remove deleted getters
       Object.keys(store._hmrPayload.getters).forEach((key) => {
         if (!(key in newStore._hmrPayload.getters)) {
-          // @ts-expect-error
           delete store[key]
         }
       })
@@ -504,7 +498,6 @@ function createSetupStore<
       // remove old actions
       Object.keys(store._hmrPayload.actions).forEach((key) => {
         if (!(key in newStore._hmrPayload.actions)) {
-          // @ts-expect-error
           delete store[key]
         }
       })
@@ -572,7 +565,7 @@ function createSetupStore<
   return store
 }
 
-// export function disposeStore(store: Store) {
+// export function disposeStore(store: StoreGeneric) {
 //   store._e
 
 // }
@@ -635,10 +628,10 @@ type _ExtractGettersFromSetupStore<SS> = _SpreadPropertiesFromObject<
  */
 export function defineStore<
   Id extends string,
-  S extends StateTree,
-  G extends GettersTree<S>,
+  S extends StateTree = {},
+  G extends GettersTree<S> = {},
   // cannot extends ActionsTree because we loose the typings
-  A /* extends ActionsTree */
+  A /* extends ActionsTree */ = {}
 >(
   id: Id,
   options: Omit<DefineStoreOptions<Id, S, G, A>, 'id'>
@@ -651,10 +644,10 @@ export function defineStore<
  */
 export function defineStore<
   Id extends string,
-  S extends StateTree,
-  G extends GettersTree<S>,
+  S extends StateTree = {},
+  G extends GettersTree<S> = {},
   // cannot extends ActionsTree because we loose the typings
-  A /* extends ActionsTree */
+  A /* extends ActionsTree */ = {}
 >(options: DefineStoreOptions<Id, S, G, A>): StoreDefinition<Id, S, G, A>
 
 /**
@@ -679,7 +672,12 @@ export function defineStore<Id extends string, SS>(
   _ExtractGettersFromSetupStore<SS>,
   _ExtractActionsFromSetupStore<SS>
 >
-export function defineStore(idOrOptions: any, setup?: any, setupOptions?: any) {
+export function defineStore(
+  // TODO: add proper types from above
+  idOrOptions: any,
+  setup?: any,
+  setupOptions?: any
+): StoreDefinition {
   let id: string
   let options:
     | DefineStoreOptions<string, StateTree, GettersTree<StateTree>, ActionsTree>
@@ -699,7 +697,7 @@ export function defineStore(idOrOptions: any, setup?: any, setupOptions?: any) {
     id = idOrOptions.id
   }
 
-  function useStore(pinia?: Pinia | null, hot?: Store): Store {
+  function useStore(pinia?: Pinia | null, hot?: StoreGeneric): StoreGeneric {
     const currentInstance = getCurrentInstance()
     pinia =
       // in test mode, ignore the argument provided as we can always retrieve a
@@ -724,7 +722,7 @@ export function defineStore(idOrOptions: any, setup?: any, setupOptions?: any) {
       }
     }
 
-    const store: Store = pinia._s.get(id)!
+    const store: StoreGeneric = pinia._s.get(id)!
 
     if (__DEV__ && hot) {
       const hotId = '__hot:' + id
@@ -736,7 +734,7 @@ export function defineStore(idOrOptions: any, setup?: any, setupOptions?: any) {
             true
           )
 
-      hot._hotUpdate(newStore as any)
+      hot._hotUpdate(newStore)
 
       // cleanup the state properties and the store from the cache
       delete pinia.state.value[hotId]
@@ -757,7 +755,8 @@ export function defineStore(idOrOptions: any, setup?: any, setupOptions?: any) {
       cache[id] = store
     }
 
-    return store
+    // StoreGeneric cannot be casted towards Store
+    return store as any
   }
 
   useStore.$id = id
index 75db70d285f029f63e9810bd6cea92d299bd2e4e..d08b844faefef3c092eb98d0c68cf68ccb11ef5c 100644 (file)
@@ -93,11 +93,7 @@ export function createTestingPinia({
     Object.keys(options.actions || {}).forEach((action) => {
       actionsCache[action] =
         actionsCache[action] ||
-        (stubActions
-          ? createSpy!()
-          : // @ts-expect-error:
-            createSpy!(store[action]))
-      // @ts-expect-error:
+        (stubActions ? createSpy!() : createSpy!(store[action]))
       store[action] = actionsCache[action]
     })
 
index 63b5a8766f9b0c27d063d53f2e9c9b170077eb7c..7367e5e4cd90aec1536ab4ad9e44512a8683f319 100644 (file)
@@ -9,7 +9,7 @@ export type StateTree = Record<string | number | symbol, any>
 /**
  * Object descriptor for Object.defineProperty
  */
-export interface StateDescriptor<S extends StateTree> {
+export interface StateDescriptor<S extends StateTree = {}> {
   get(): S
   set(newValue: S): void
 }
@@ -163,7 +163,7 @@ export type SubscriptionCallback<S> = (
 export type StoreOnActionListenerContext<
   Id extends string,
   S extends StateTree,
-  G extends GettersTree<S>,
+  G /* extends GettersTree<S> */,
   A /* extends ActionsTree */
 > = {
   [Name in keyof A]: {
@@ -175,7 +175,7 @@ export type StoreOnActionListenerContext<
     /**
      * Store that is invoking the action
      */
-    store: Store<Id, S, G, A>
+    store: ActionsTree extends A ? StoreGeneric : Store<Id, S, G, A>
 
     /**
      * Parameters passed to the action
@@ -208,11 +208,19 @@ export type StoreOnActionListenerContext<
  * Argument of `store.$onAction()`
  */
 export type StoreOnActionListener<
-  Id extends string = string,
-  S extends StateTree = StateTree,
-  G extends GettersTree<S> = GettersTree<S>,
-  A /* extends ActionsTree */ = ActionsTree
-> = (context: StoreOnActionListenerContext<Id, S, G, A>) => void
+  Id extends string,
+  S extends StateTree,
+  G /* extends GettersTree<S> */,
+  A /* extends ActionsTree */
+> = (
+  context: StoreOnActionListenerContext<
+    Id,
+    S,
+    G,
+    // {} creates a type of never due to how StoreOnActionListenerContext is defined
+    {} extends A ? ActionsTree : A
+  >
+) => void
 
 /**
  * Base store with state and functions
@@ -221,8 +229,8 @@ export type StoreOnActionListener<
 export interface StoreWithState<
   Id extends string,
   S extends StateTree,
-  G extends GettersTree<StateTree> = GettersTree<S>,
-  A /* extends ActionsTree */ = ActionsTree
+  G /* extends GettersTree<StateTree> */,
+  A /* extends ActionsTree */
 > {
   /**
    * Unique identifier of the store
@@ -232,8 +240,7 @@ export interface StoreWithState<
   /**
    * State of the Store. Setting it will replace the whole state.
    */
-  $state: UnwrapRef<StateTree extends S ? {} : S> &
-    PiniaCustomStateProperties<S>
+  $state: UnwrapRef<S> & PiniaCustomStateProperties<S>
 
   /**
    * Private property defining the pinia the store is attached to.
@@ -250,7 +257,9 @@ export interface StoreWithState<
   _getters?: string[]
 
   /**
-   * Used by devtools plugin to retrieve properties added with plugins. Removed in production.
+   * Used by devtools plugin to retrieve properties added with plugins. Removed
+   * in production. Can be used by the user to add property keys of the store
+   * that should be displayed in devtools.
    *
    * @internal
    */
@@ -261,7 +270,7 @@ export interface StoreWithState<
    *
    * @internal
    */
-  _hotUpdate(useStore: Store<Id, S, G, A>): void
+  _hotUpdate(useStore: StoreGeneric): void
 
   /**
    * Payload of the hmr update. Dev only.
@@ -393,26 +402,39 @@ export type StoreWithGetters<G> = {
  */
 export type Store<
   Id extends string = string,
-  S extends StateTree = StateTree,
-  G extends GettersTree<S> = GettersTree<S>,
+  S extends StateTree = {},
+  G /* extends GettersTree<S>*/ = {},
   // has the actions without the context (this) for typings
-  A /* extends ActionsTree */ = ActionsTree
-> = StoreWithState<Id, StateTree extends S ? {} : S, G, A> &
-  (StateTree extends S ? {} : UnwrapRef<S>) &
-  (GettersTree<S> extends G ? {} : StoreWithGetters<G>) &
+  A /* extends ActionsTree */ = {}
+> = StoreWithState<Id, S, G, A> &
+  UnwrapRef<S> &
+  StoreWithGetters<G> &
+  // StoreWithActions<A> &
   (ActionsTree extends A ? {} : StoreWithActions<A>) &
   PiniaCustomProperties<Id, S, G, A> &
   PiniaCustomStateProperties<S>
+/**
+ * Generic and type-unsafe version of Store. Doesn't fail on access with
+ * strings, making it much easier to write generic functions that do not care
+ * about the kind of store that is passed.
+ */
+export type StoreGeneric = Store<
+  string,
+  StateTree,
+  GettersTree<StateTree>,
+  ActionsTree
+>
 
 /**
  * Generic and type-unsafe version of Store. Doesn't fail on access with
  * strings, making it much easier to write generic functions that do not care
  * about the kind of store that is passed.
+ * @deprecated Use `StoreGeneric` instead
  */
 export type GenericStore<
   Id extends string = string,
-  S extends StateTree = any,
-  G extends GettersTree<S> = GettersTree<S>,
+  S extends StateTree = StateTree,
+  G /* extends GettersTree<S> */ = GettersTree<S>,
   // has the actions without the context (this) for typings
   A /* extends ActionsTree */ = ActionsTree
 > = StoreWithState<Id, S, G, A> &
@@ -428,7 +450,7 @@ export type GenericStore<
 export interface StoreDefinition<
   Id extends string = string,
   S extends StateTree = StateTree,
-  G extends GettersTree<S> = GettersTree<S>,
+  G /* extends GettersTree<S>*/ = GettersTree<S>,
   A /* extends ActionsTree */ = ActionsTree
 > {
   /**
@@ -437,7 +459,12 @@ export interface StoreDefinition<
    * @param pinia - Pinia instance to retrieve the store
    * @param hot - dev only hot module replacement
    */
-  (pinia?: Pinia | null | undefined, hot?: Store): Store<Id, S, G, A>
+  (pinia?: Pinia | null | undefined, hot?: Store<Id, S, G, A>): Store<
+    Id,
+    S,
+    G,
+    A
+  >
 
   /**
    * Id of the store. Used by map helpers.
@@ -458,7 +485,7 @@ export interface StoreDefinition<
 export interface PiniaCustomProperties<
   Id extends string = string,
   S extends StateTree = StateTree,
-  G extends GettersTree<S> = GettersTree<S>,
+  G /* extends GettersTree<S> */ = GettersTree<S>,
   A /* extends ActionsTree */ = ActionsTree
 > {}
 
@@ -474,11 +501,7 @@ export interface PiniaCustomStateProperties<S extends StateTree = StateTree> {}
  */
 export type GettersTree<S extends StateTree> = Record<
   string,
-  | ((
-      state: UnwrapRef<
-        (StateTree extends S ? {} : S) & PiniaCustomStateProperties<S>
-      >
-    ) => any)
+  | ((state: UnwrapRef<S> & UnwrapRef<PiniaCustomStateProperties<S>>) => any)
   | (() => any)
 >
 
@@ -496,7 +519,7 @@ export type ActionsTree = Record<string, _Method>
 export interface DefineStoreOptions<
   Id extends string,
   S extends StateTree,
-  G extends GettersTree<S>,
+  G /* extends GettersTree<S> */,
   A /* extends Record<string, StoreAction> */
 > {
   /**
@@ -513,11 +536,8 @@ export interface DefineStoreOptions<
    * Optional object of getters.
    */
   getters?: G &
-    ThisType<
-      UnwrapRef<StateTree extends S ? {} : S> &
-        StoreWithGetters<G> &
-        PiniaCustomProperties
-    >
+    ThisType<UnwrapRef<S> & StoreWithGetters<G> & PiniaCustomProperties> &
+    GettersTree<S>
 
   /**
    * Optional object of actions.
@@ -525,9 +545,9 @@ export interface DefineStoreOptions<
   actions?: A &
     ThisType<
       A &
-        UnwrapRef<StateTree extends S ? {} : S> &
+        UnwrapRef<S> &
         StoreWithState<Id, S, G, A> &
-        StoreWithGetters<GettersTree<S> extends G ? {} : G> &
+        StoreWithGetters<G> &
         PiniaCustomProperties
     >
 
@@ -544,7 +564,7 @@ export interface DefineStoreOptions<
 export interface DefineSetupStoreOptions<
   Id extends string,
   S extends StateTree,
-  G extends ActionsTree, // TODO: naming
+  G,
   A /* extends ActionsTree */
 > extends Omit<
     DefineStoreOptions<Id, S, G, A>,
@@ -564,8 +584,8 @@ export interface DefineSetupStoreOptions<
 export interface DefineStoreOptionsInPlugin<
   Id extends string,
   S extends StateTree,
-  G extends ActionsTree, // TODO: naming
-  A /* extends ActionsTree */
+  G,
+  A
 > extends Omit<DefineStoreOptions<Id, S, G, A>, 'id'> {
   /**
    * Extracted object of actions. Added by useStore() when the store is built
index 0eeb6922da90b98ed9b528c9aec119331fabd094..71746081cec920ca078da24895a2567630fa461b 100644 (file)
@@ -103,7 +103,6 @@ pinia.use(({ options, store }) => {
   if (options.debounce) {
     return Object.keys(options.debounce).reduce((debouncedActions, action) => {
       debouncedActions[action] = debounce(
-        // @ts-expect-error: cannot be inferred
         store[action],
         options.debounce![action as keyof typeof options['actions']]
       )
index 5034a82e7c51cf1fd563dd00f656f4453adf4926..2e9df04353a7fb433ce705387f173d6344640b37 100644 (file)
@@ -1,4 +1,5 @@
 export * from '../dist/pinia'
+// export * from '../src'
 
 export function describe(_name: string, _fn: () => void): void
 export function expectType<T>(value: T): void
index ddf688810aa59b5ef584c1b9f9ae83354dc66eef..c3b37b6a615c1c376efa8112fa1e6e4b429329ea 100644 (file)
@@ -2,7 +2,7 @@ import { App } from 'vue'
 import {
   expectType,
   createPinia,
-  Store,
+  StoreGeneric,
   Pinia,
   StateTree,
   DefineStoreOptionsInPlugin,
@@ -11,7 +11,7 @@ import {
 const pinia = createPinia()
 
 pinia.use(({ store, app, options, pinia }) => {
-  expectType<Store>(store)
+  expectType<StoreGeneric>(store)
   expectType<Pinia>(pinia)
   expectType<App>(app)
   expectType<
index 19f702a550b246e84892f74d711b7a7c7f4b79dd..ed2faa73fe012edbaf020d22fd391604f1f0a824 100644 (file)
@@ -1,5 +1,5 @@
+import { StoreGeneric, defineStore, expectType } from './'
 import { watch } from 'vue'
-import { defineStore, expectType, Store, GenericStore } from './'
 
 const useStore = defineStore({
   id: 'name',
@@ -205,12 +205,12 @@ noA.notExisting
 // @ts-expect-error
 noG.notExisting
 
-function takeStore<TStore extends Store>(store: TStore): TStore['$id'] {
+function takeStore<TStore extends StoreGeneric>(store: TStore): TStore['$id'] {
   return store.$id
 }
 
 export const useSyncValueToStore = <
-  TStore extends Store,
+  TStore extends StoreGeneric,
   TKey extends keyof TStore['$state']
 >(
   propGetter: () => TStore[TKey],
@@ -247,12 +247,13 @@ useSyncValueToStore(() => 2, noA, 'myState')
 takeStore(noG)
 useSyncValueToStore(() => 2, noG, 'myState')
 
-declare var genericStore: GenericStore
+declare var genericStore: StoreGeneric
 
 // should not fail like it does with Store
 expectType<any>(genericStore.thing)
 expectType<any>(genericStore.$state.thing)
 takeStore(genericStore)
 useSyncValueToStore(() => 2, genericStore, 'myState')
+// @ts-expect-error: this type is known so it should yield an error
 useSyncValueToStore(() => false, genericStore, 'myState')
 useSyncValueToStore(() => 2, genericStore, 'random')