Skip to content

Commit

Permalink
fix: make TS type defs conform to redux 4
Browse files Browse the repository at this point in the history
  • Loading branch information
jedwards1211 committed Nov 9, 2023
1 parent d6eefa8 commit ed1126d
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 91 deletions.
3 changes: 3 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ module.exports = {
env: {
es6: true,
},
rules: {
'@typescript-eslint/ban-types': 0,
},
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"flow-bin": "^0.97.0",
"mindfront-redux-utils": "^2.0.0",
"mocha": "^10.2.0",
"redux": "^3.6.0",
"redux": "^4.2.1",
"rimraf": "^2.6.0",
"sinon": "^1.17.6",
"typescript": "^5.2.2",
Expand Down
16 changes: 14 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 11 additions & 10 deletions src/actions.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AnyAction } from 'redux'
import type { Feature, FeatureState, FeatureAction } from './index'
export declare const ACTION_TYPE_PREFIX = '@@redux-features/'
export declare const ADD_FEATURE: '@@redux-features/ADD_FEATURE'
Expand All @@ -6,19 +7,19 @@ export declare const LOAD_FEATURE: '@@redux-features/LOAD_FEATURE'
export declare const INSTALL_FEATURE: '@@redux-features/INSTALL_FEATURE'
export declare const SET_FEATURE_STATE: '@@redux-features/SET_FEATURE_STATE'
export declare const LOAD_INITIAL_FEATURES: '@@redux-features/LOAD_INITIAL_FEATURES'
export declare function addFeature<S>(
export declare function addFeature<S = any, A extends AnyAction = AnyAction>(
id: string,
feature: Feature<S>
): FeatureAction
export declare function replaceFeature<S>(
id: string,
feature: Feature<S>
feature: Feature<S, A>
): FeatureAction
export declare function replaceFeature<
S = any,
A extends AnyAction = AnyAction
>(id: string, feature: Feature<S, A>): FeatureAction
export declare function loadFeature(id: string): FeatureAction
export declare function installFeature<S>(
id: string,
feature: Feature<S>
): FeatureAction
export declare function installFeature<
S = any,
A extends AnyAction = AnyAction
>(id: string, feature: Feature<S, A>): FeatureAction
export declare function setFeatureState(
id: string,
payload: FeatureState
Expand Down
45 changes: 28 additions & 17 deletions src/defaults.d.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import type { Reducer, Middleware } from 'redux'
export declare const defaultCreateReducer: (<S>(
initialState: S,
reducers: {
[actionType: string]: Reducer<S>
}
) => Reducer<S>) &
(<S>(reducers: { [actionType: string]: Reducer<S> }) => Reducer<S>)
export declare function defaultComposeReducers<S>(
...reducers: Array<Reducer<S>>
): Reducer<S>
export declare function defaultCreateMiddleware(middlewares: {
[actionType: string]: Middleware
}): Middleware
export declare function defaultComposeMiddleware(
...middlewares: Array<Middleware>
): Middleware
import type { Reducer, Middleware, AnyAction, Dispatch } from 'redux'
export declare const defaultCreateReducer: {
<S = any, A extends AnyAction = AnyAction>(
initialState: S,
reducers: Record<string, Reducer<S, A>>
): Reducer<S, A>
<S = any, A extends AnyAction = AnyAction>(
reducers: Record<string, Reducer<S, A>>
): Reducer<S, A>
}
export declare function defaultComposeReducers<
S = any,
A extends AnyAction = AnyAction
>(...reducers: Array<Reducer<S, A>>): Reducer<S, A>
export declare function defaultCreateMiddleware<
DispatchExt = {},
S = any,
D extends Dispatch = Dispatch
>(
middlewares: Record<string, Middleware<DispatchExt, S, D>>
): Middleware<DispatchExt, S, D>
export declare function defaultComposeMiddleware<
DispatchExt = {},
S = any,
D extends Dispatch = Dispatch
>(
...middlewares: Array<Middleware<DispatchExt, S, D>>
): Middleware<DispatchExt, S, D>
14 changes: 9 additions & 5 deletions src/featureMiddlewaresMiddleware.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import type { Middleware } from 'redux'
import type { Dispatch, Middleware } from 'redux'
import type { Features, ComposeMiddleware } from './index'
export default function featureMiddlewaresMiddleware<S>(config?: {
getFeatures?: (state: S) => Features<S> | null | undefined
composeMiddleware?: ComposeMiddleware
}): Middleware
export default function featureMiddlewaresMiddleware<
DispatchExt = {},
S = any,
D extends Dispatch = Dispatch
>(config?: {
getFeatures?: (state: S) => Features<S, Parameters<D>[0]> | null | undefined
composeMiddleware?: ComposeMiddleware<DispatchExt, S, D>
}): Middleware<DispatchExt, S, D>
13 changes: 8 additions & 5 deletions src/featureReducersReducer.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import type { Reducer } from 'redux'
import type { AnyAction, Reducer } from 'redux'
import type { Features, ComposeReducers } from './index'
export default function featureReducersReducer<S>(config?: {
getFeatures?: (state: S) => Features<S> | null | undefined
composeReducers?: ComposeReducers<S>
}): Reducer<S>
export default function featureReducersReducer<
S = any,
A extends AnyAction = AnyAction
>(config?: {
getFeatures?: (state: S) => Features<S, A> | null | undefined
composeReducers?: ComposeReducers<S, A>
}): Reducer<S, A>
9 changes: 5 additions & 4 deletions src/featureStatesReducer.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Reducer } from 'redux'
import type { FeatureStates, CreateReducer } from './index'
export default function featureStatesReducer(config?: {
createReducer?: CreateReducer<FeatureStates>
}): Reducer<FeatureStates>
import type { FeatureStates, CreateReducer, FeatureAction } from './index'
export default function featureStatesReducer<
S extends FeatureStates = FeatureStates,
A extends FeatureAction = FeatureAction
>(config?: { createReducer?: CreateReducer<S, A> }): Reducer<S, A>
12 changes: 8 additions & 4 deletions src/featuresReducer.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import type { Reducer } from 'redux'
import type { AnyAction, Dispatch, Reducer } from 'redux'
import type { Features, CreateReducer } from './index'
export default function featuresReducer<S>(config?: {
createReducer?: CreateReducer<Features<S>>
}): Reducer<Features<S>>
export default function featuresReducer<
S = any,
A extends AnyAction = AnyAction,
D extends Dispatch = Dispatch<A>
>(config?: {
createReducer?: CreateReducer<Features<S, A>>
}): Reducer<Features<S, A, D>>
64 changes: 37 additions & 27 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,47 @@ export {
setFeatureState,
loadInitialFeatures,
}
import type { MiddlewareAPI, Reducer, Middleware, ActionCreator } from 'redux'
export type ActionCreators<K extends string | number | symbol, A> = Partial<
Record<K, ActionCreator<A>>
>
export interface CreateReducer<S> {
(
initialState: S,
reducers: {
[actionType: string]: Reducer<S>
}
): Reducer<S>
(reducers: { [actionType: string]: Reducer<S> }): Reducer<S>
import type {
MiddlewareAPI,
Reducer,
Middleware,
AnyAction,
Dispatch,
} from 'redux'

export interface CreateReducer<S, A extends AnyAction = AnyAction> {
(initialState: S, reducers: Record<A['type'], Reducer<S, A>>): Reducer<S>
(reducers: Record<A['type'], Reducer<S, A>>): Reducer<S>
}
export type ComposeReducers<S> = (...reducers: Array<Reducer<S>>) => Reducer<S>
export type ComposeMiddleware = (
...middlewares: Array<Middleware>
) => Middleware
export type ComposeReducers<S, A extends AnyAction = AnyAction> = (
...reducers: Array<Reducer<S, A>>
) => Reducer<S, A>
export type ComposeMiddleware<
DispatchExt = {},
S = any,
D extends Dispatch = Dispatch
> = (
...middlewares: Array<Middleware<DispatchExt, S, D>>
) => Middleware<DispatchExt, S, D>
export type FeatureState = 'NOT_LOADED' | 'LOADING' | 'LOADED' | Error
export type FeatureStates = {
[featureId: string]: FeatureState
}
export type Feature<S> = {
init?: (store: MiddlewareAPI<S>) => any
load?: (store: MiddlewareAPI<S>) => Promise<Feature<S>>
export type FeatureStates = Record<string, FeatureState>
export type Feature<
S = any,
A extends AnyAction = AnyAction,
D extends Dispatch = Dispatch<A>
> = {
init?: (store: MiddlewareAPI<D, S>) => any
load?: (store: MiddlewareAPI<D, S>) => Promise<Feature<S, A>>
dependencies?: Array<string>
middleware?: Middleware
reducer?: Reducer<S>
}
export type Features<S> = {
[featureId: string]: Feature<S>
middleware?: Middleware<any, S, D>
reducer?: Reducer<S, A>
}
export type Features<
S,
A extends AnyAction = AnyAction,
D extends Dispatch = Dispatch<A>
> = Record<string, Feature<S, A, D>>

export type FeatureAction = {
type: string
payload?: any
Expand Down
20 changes: 13 additions & 7 deletions src/loadFeatureMiddleware.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import type { Features, FeatureStates } from './index'
import type { Middleware } from 'redux'
export default function loadFeatureMiddleware<S>(config?: {
getFeatures?: (state: S) => Features<S> | null | undefined
import type { Dispatch, Middleware } from 'redux'
export default function loadFeatureMiddleware<
DispatchExt = {},
S = any,
D extends Dispatch = Dispatch
>(config?: {
getFeatures?: (
state: S
) => Features<S, Parameters<D>[0], D> | null | undefined
getFeatureStates?: (state: S) => FeatureStates | null | undefined
createMiddleware?: (middlewares: {
[actionType: string]: Middleware
}) => Middleware
}): Middleware
createMiddleware?: (
middlewares: Record<string, Middleware<DispatchExt, S, D>>
) => Middleware<DispatchExt, S, D>
}): Middleware<DispatchExt, S, D>
22 changes: 14 additions & 8 deletions test/typecheck.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import type { Features, FeatureStates, FeatureAction } from '../src/index'
import type {
Features,
FeatureStates,
FeatureAction,
Feature,
} from '../src/index'
import {
composeReducers,
featuresReducer,
Expand All @@ -19,22 +24,23 @@ type Action =
}
| FeatureAction
type State = {
features: Features<State>
features: Features<State, Action>
featureStates: FeatureStates
}
const reducer: Reducer<State> = composeReducers(
const reducer: Reducer<State, Action> = composeReducers(
combineReducers({
features: featuresReducer(),
featureStates: featureStatesReducer(),
}),
featureReducersReducer()
)
const store: Store<State> = createStore(
const store: Store<State, Action> = createStore(
reducer,
applyMiddleware(loadFeatureMiddleware(), featureMiddlewaresMiddleware())
)
const feature = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
reducer: (state: State | undefined, action: Action) => state,
} as const
const feature: Feature<State, Action> = {
// eslint-disable-next-line no-unused-vars
reducer: (state: State | undefined, action: Action) =>
state || { features: {}, featureStates: {} },
}
store.dispatch(addFeature('test', feature))
5 changes: 4 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
{
"extends": "./node_modules/@jcoreio/toolchain-typescript/tsconfig.json",
"include": ["./src"],
"exclude": ["node_modules"]
"exclude": ["node_modules"],
"compilerOptions": {
"skipLibCheck": false
}
}

0 comments on commit ed1126d

Please sign in to comment.