Skip to content

Commit

Permalink
Improve type of selectors map
Browse files Browse the repository at this point in the history
Improve the type of the `selectors` argument to `createStoreModule` to
link it to the type of the initial state returned by the `initialState`
argument. This enables TS to check/infer that the first argument to
these functions should be of the same type that `initialState` returns.

In the process it was necessary to remove the `ModuleConfig` type and
declare the type of `createStoreModule`'s `config` argument inline.
This works around a TypeScript limitation [1]:

```
@template State
@template {SelectorMap<State>} Selectors // Unexpected error
...
@typedef ModuleConfig
```

But this works:

``
@template State
@template {SelectorMap<State>} Selectors // OK
...
function createStoreModule(...) { ... }
```

[1] microsoft/TypeScript#43403
  • Loading branch information
robertknight committed Jun 7, 2021
1 parent a118356 commit 4fd547b
Showing 1 changed file with 24 additions and 19 deletions.
43 changes: 24 additions & 19 deletions src/sidebar/store/create-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,31 @@ import { createReducer, bindSelectors } from './util';
*/

/**
* Map of action name to reducer function.
* Map of action type to reducer function.
*
* @template State
* @typedef {{ [action: string]: (s: State, action: any) => Partial<State> }} Reducers
* @typedef {{ [action: string]: (s: State, action: any) => Partial<State> }} ReducerMap
*/

/**
* Configuration for a store module.
* Map of selector name to selector function.
*
* @template State
* @typedef {{ [name: string]: (s: State, ...args: any[]) => any }} SelectorMap
*/

/**
* Type of a store module returned by `createStoreModule`.
*
* @template State
* @template {object} Actions
* @template {object} Selectors
* @template {object} RootSelectors
* @typedef ModuleConfig
* @typedef Module
* @prop {string} namespace -
* The key under which this module's state will live in the store's root state
* @prop {Reducers<State>} reducers -
* @prop {(...args: any[]) => State} initialState
* @prop {ReducerMap<State>} reducers -
* Map of action types to "reducer" functions that process an action and return
* the changes to the state
* @prop {Actions} actionCreators
Expand All @@ -49,18 +57,6 @@ import { createReducer, bindSelectors } from './util';
* @prop {RootSelectors} [rootSelectors]
*/

/**
* Type of a store module returned by `createStoreModule`.
*
* @template State
* @template {object} Actions
* @template {object} Selectors
* @template {object} RootSelectors
* @typedef {ModuleConfig<State, Actions, Selectors, RootSelectors> & {
* initialState: (...args: any[]) => State
* }} Module
*/

/**
* Replace a type `T` with `Fallback` if `T` is `any`.
*
Expand Down Expand Up @@ -191,15 +187,24 @@ export function createStore(modules, initArgs = [], middleware = []) {
return store;
}

// The properties of the `config` argument to `createStoreModule` below are
// declared inline due to https://github.com/microsoft/TypeScript/issues/43403.

/**
* Create a store module that can be passed to `createStore`.
*
* @template State
* @template Actions
* @template Selectors
* @template {SelectorMap<State>} Selectors
* @template RootSelectors
* @param {(...args: any[]) => State} initialState
* @param {ModuleConfig<State,Actions,Selectors,RootSelectors>} config
* @param {object} config
* @param {string} config.namespace -
* The key under which this module's state will live in the store's root state
* @param {ReducerMap<State>} config.reducers -
* @param {Actions} config.actionCreators
* @param {Selectors} config.selectors
* @param {RootSelectors} [config.rootSelectors]
* @return {Module<State,Actions,Selectors,RootSelectors>}
*/
export function createStoreModule(initialState, config) {
Expand Down

0 comments on commit 4fd547b

Please sign in to comment.