Update DispatchingStore to provide better typing for dispatch function parameters

This commit is contained in:
Andrew Bastin
2021-05-25 18:27:50 -04:00
parent baf6d6bd29
commit 21aeded2ea
3 changed files with 39 additions and 28 deletions

View File

@@ -3,28 +3,37 @@ import { map } from "rxjs/operators"
import assign from "lodash/assign"
import clone from "lodash/clone"
export type Dispatchers<StoreType> = {
[key: string]: (currentVal: StoreType, payload: any) => Partial<StoreType>
}
type dispatcherFunc<StoreType> = (
currentVal: StoreType,
payload: any
) => Partial<StoreType>
/**
* Defines a dispatcher.
*
* This function exists to provide better typing for dispatch function.
* As you can see, its pretty much an identity function.
*/
export const defineDispatchers = <StoreType, T>(
// eslint-disable-next-line no-unused-vars
dispatchers: { [_ in keyof T]: dispatcherFunc<StoreType> }
) => dispatchers
type Dispatch<
StoreType,
DispatchersType extends Dispatchers<StoreType>,
K extends keyof DispatchersType
DispatchersType extends Record<string, dispatcherFunc<StoreType>>
> = {
dispatcher: K & string
dispatcher: keyof DispatchersType
payload: any
}
export default class DispatchingStore<
StoreType,
DispatchersType extends Dispatchers<StoreType>
DispatchersType extends Record<string, dispatcherFunc<StoreType>>
> {
#state$: BehaviorSubject<StoreType>
#dispatchers: Dispatchers<StoreType>
#dispatches$: Subject<
Dispatch<StoreType, DispatchersType, keyof DispatchersType>
> = new Subject()
#dispatchers: DispatchersType
#dispatches$: Subject<Dispatch<StoreType, DispatchersType>> = new Subject()
constructor(initialValue: StoreType, dispatchers: DispatchersType) {
this.#state$ = new BehaviorSubject(initialValue)
@@ -56,10 +65,7 @@ export default class DispatchingStore<
return this.#dispatches$
}
dispatch({
dispatcher,
payload,
}: Dispatch<StoreType, DispatchersType, keyof DispatchersType>) {
dispatch({ dispatcher, payload }: Dispatch<StoreType, DispatchersType>) {
if (!this.#dispatchers[dispatcher])
throw new Error(`Undefined dispatch type '${dispatcher}'`)

View File

@@ -1,6 +1,6 @@
import eq from "lodash/eq"
import { pluck } from "rxjs/operators"
import DispatchingStore, { Dispatchers } from "./DispatchingStore"
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
export const defaultRESTHistoryState = {
state: [] as any[],
@@ -15,18 +15,21 @@ export const HISTORY_LIMIT = 50
type RESTHistoryType = typeof defaultRESTHistoryState
type GraphqlHistoryType = typeof defaultGraphqlHistoryState
const HistoryDispatcher: Dispatchers<RESTHistoryType | GraphqlHistoryType> = {
setEntries(_, { entries }: { entries: any[] }) {
const HistoryDispatcher = defineDispatchers({
setEntries(
_: RESTHistoryType | GraphqlHistoryType,
{ entries }: { entries: any[] }
) {
return {
state: entries,
}
},
addEntry(currentVal, { entry }) {
addEntry(currentVal: RESTHistoryType | GraphqlHistoryType, { entry }) {
return {
state: [entry, ...currentVal.state].slice(0, HISTORY_LIMIT),
}
},
deleteEntry(currentVal, { entry }) {
deleteEntry(currentVal: RESTHistoryType | GraphqlHistoryType, { entry }) {
return {
state: currentVal.state.filter((e) => !eq(e, entry)),
}
@@ -36,7 +39,7 @@ const HistoryDispatcher: Dispatchers<RESTHistoryType | GraphqlHistoryType> = {
state: [],
}
},
toggleStar(currentVal, { entry }) {
toggleStar(currentVal: RESTHistoryType | GraphqlHistoryType, { entry }) {
return {
state: currentVal.state.map((e) => {
if (eq(e, entry) && e.star !== undefined) {
@@ -49,7 +52,7 @@ const HistoryDispatcher: Dispatchers<RESTHistoryType | GraphqlHistoryType> = {
}),
}
},
}
})
export const restHistoryStore = new DispatchingStore(
defaultRESTHistoryState,

View File

@@ -1,8 +1,7 @@
import { pluck, distinctUntilChanged } from "rxjs/operators"
import has from "lodash/has"
import { Observable } from "rxjs"
import DispatchingStore from "./DispatchingStore"
import type { Dispatchers } from "./DispatchingStore"
import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
import type { KeysMatching } from "~/types/ts-utils"
export const defaultSettings = {
@@ -28,12 +27,15 @@ export type SettingsType = typeof defaultSettings
const validKeys = Object.keys(defaultSettings)
const dispatchers: Dispatchers<SettingsType> = {
bulkApplySettings(_currentState, payload: Partial<SettingsType>) {
const dispatchers = defineDispatchers({
bulkApplySettings(
_currentState: SettingsType,
payload: Partial<SettingsType>
) {
return payload
},
toggleSetting(
currentState,
currentState: SettingsType,
{ settingKey }: { settingKey: KeysMatching<SettingsType, boolean> }
) {
if (!has(currentState, settingKey)) {
@@ -80,7 +82,7 @@ const dispatchers: Dispatchers<SettingsType> = {
return result
},
}
})
export const settingsStore = new DispatchingStore(defaultSettings, dispatchers)