})
```
-`PiniaCustomProperties` is a generic type that allows you to reference properties of a store. Imagine the following example where we copy over the initial options as `$options`:
+`PiniaCustomProperties` is a generic type that allows you to reference properties of a store. Imagine the following example where we copy over the initial options as `$options` (this would only work for option stores):
```ts
pinia.use(({ options }) => ({ $options: options }))
import 'pinia'
declare module 'pinia' {
- export interface PiniaCustomProperties<Id, State, Getters, Actions> {
+ export interface PiniaCustomProperties<Id, S, G, A> {
$options: {
id: Id
- state?: () => State
- getters?: Getters
- actions?: Actions
+ state?: () => S
+ getters?: G
+ actions?: A
}
}
}
```
+:::tip
+When extending types in generics, they must be named **exactly as in the source code**. `Id` cannot be named `id` or `I`, and `S` cannot be named `State`. Here is what every letter stands for:
+
+- S: State
+- G: Getters
+- A: Actions
+- SS: Setup Store / Store
+
+:::
+
### Typing new state
When adding new state properties (to both, the `store` and `store.$state`), you need to add the type to `PiniaCustomStateProperties` instead. Differently from `PiniaCustomProperties`, it only receives the `State` generic:
import 'pinia'
declare module 'pinia' {
- export interface PiniaCustomStateProperties<State> {
+ export interface PiniaCustomStateProperties<S> {
hello: string
}
}
### Typing new creation options
-When creating new options for `defineStore()`, you should extend the `DefineStoreOptions`. Like `PiniaCustomProperties`, it also exposes all the generics that define a store, allowing you to limit what can be defined. For example, you can une the names of the actions:
+When creating new options for `defineStore()`, you should extend the `DefineStoreOptionsBase`. Differently from `PiniaCustomProperties`, it only exposes two generics: the State and the Store type, allowing you to limit what can be defined. For example, you can une the names of the actions:
```ts
import 'pinia'
declare module 'pinia' {
- export interface DefineStoreOptions<Id, State, Getters, Actions> {
+ export interface DefineStoreOptionsBase<S, Store> {
debounce?: {
// allow defining a number of ms for any of the actions
[k in keyof A]?: number
StateTree,
Store,
StoreGeneric,
+ // TODO: remove in release
GenericStore,
StoreDefinition,
StoreWithGetters,
_Method,
StoreWithActions,
StoreWithState,
+ StoreProperties,
StoreOnActionListener,
StoreOnActionListenerContext,
SubscriptionCallback,
} from './mapHelpers'
export { createTestingPinia } from './testing'
-export type { TestingOptions } from './testing'
+export type { TestingOptions, TestingPinia } from './testing'
export { acceptHMRUpdate } from './hmr'
// }
+/**
+ * @internal
+ */
type _SpreadStateFromStore<SS, K extends readonly any[]> = K extends readonly [
infer A,
...infer Rest
: {}
: {}
+/**
+ * @internal
+ */
type _SpreadPropertiesFromObject<
SS,
K extends readonly any[],
: {}
: {}
+/**
+ * @internal
+ */
type _ExtractStateFromSetupStore<SS> = _SpreadStateFromStore<
SS,
_UnionToTuple<keyof SS>
>
+/**
+ * @internal
+ */
type _ExtractActionsFromSetupStore<SS> = _SpreadPropertiesFromObject<
SS,
_UnionToTuple<keyof SS>,
_Method
>
+/**
+ * @internal
+ */
type _ExtractGettersFromSetupStore<SS> = _SpreadPropertiesFromObject<
SS,
_UnionToTuple<keyof SS>,
createSpy?: (fn?: (...args: any[]) => any) => (...args: any[]) => any
}
+/**
+ * Pinia instance specifically designed for testing. Extends a regular
+ * {@link Pinia} instance with test specific properties.
+ */
export interface TestingPinia extends Pinia {
/**
* Clears the cache of spies used for actions.
* they are replaced with `jest.fn()`, otherwise, you must provide your own
* `createSpy` option.
*
- * @internal - STILL NOT RELEASED, DO NOT USE. It will be likely moved to its
+ * @alpha - STILL NOT RELEASED, DO NOT USE. It will be likely moved to its
* own package.
*
* @param options - options to configure the testing pinia
plugins.forEach((plugin) => pinia.use(plugin))
- // @ts-ignore
+ // @ts-ignore: this can fail in TS depending of the existence of jest
createSpy = createSpy || (typeof jest !== undefined && jest.fn)
if (!createSpy) {
throw new Error('You must configure the `createSpy` option.')
)
}
+/**
+ * Recursive `Partial<T>`. Used by {@link Store.$patch}.
+ *
+ * @internal
+ */
export type DeepPartial<T> = { [K in keyof T]?: DeepPartial<T[K]> }
// type DeepReadonly<T> = { readonly [P in keyof T]: DeepReadonly<T[P]> }
}
/**
- * Properties that are added to every store by `pinia.use()`
+ * Properties that are added to every store by `pinia.use()`.
*/
export interface PiniaCustomProperties<
Id extends string = string,
> {}
/**
- * Properties that are added to every `store.$state` by `pinia.use()`
+ * Properties that are added to every `store.$state` by `pinia.use()`.
*/
export interface PiniaCustomStateProperties<S extends StateTree = StateTree> {}
/**
- * Type of an object of Getters that infers the argument
+ * Type of an object of Getters that infers the argument.
*
* @internal
*/
>
/**
- * Type of an object of Actions
+ * Type of an object of Actions.
*
* @internal
*/