redutser
Type-safe action creators and reducers for redux and typescript.
In a nutshell
Allows you to write type-safe reducers with fewer keystrokes. Just write the functions, the lib cares about the action creators and the types.
typescript versions: If your project uses ts2.8, you'll have to install another version of the package.
Version | package |
---|---|
2.9 | redutser |
2.8 | redutser@ts2.8 |
createRedutser( initialState, actionsDict ): Redutser
actionsDict
is an object which keys will become the action types, and which values
will become the reducer logic.
When writing the actionDict
(second parameter), it is expected that:
- Each value is a function with shape
(prevState: State, action: A) => State
; - The
State
type is inferred from the initial state you formerly passed as the 1st argument; - You need to supply the second argument's type.
- You write
actionsDict
directly inside thecreateRedutser
call ("inline"), otherwise you'd need to duck-type theState
type for every item.
Using this
? See caveat.
The returning object has the following properties:
Redutser#reducer
The generated reducer function, which you can directly feed into createStore
or compose
with another reducer.
// .reducer has a reducer with exactly the shape you are thinking of.
Redutser#reducerWithInitializer
Creates a reducer function with a different initializer from the previously supplied. (this may probably help on SSR scenarios)
Redutser#creators
A collection of action creators, properly named and typed according to the actionDict
you
previously supplied.
// .actionCreators contains an action creator mapstore.dispatchactions.feed_append
Redutser#actionTypes
This exports the generated reducer's action type. Which is a union of all of the possible action inputs. You can use this to describe accurate dispatch functions.
Note: this meant to be always used with typeof
.
React helpers
experimental
Redutser#plug
This is intended to be an easier shorthand to react-redux.connect
. (react-redux is required as a peer dependency in order to use this).
.ownProps .mapProps , .component
- In order to simplify, only a subset of
connect
's use cases is covered; - The
connect
's type arguments are spread into separate function calls in order to aid inference (that's a workaround for the lack partial argument inference); State
andActionTypes
inferred from context redutser;ownProps
type argument is optional and defaults to{}
- the
ownProps
call is optional (can be skipped) mapProps
arguments are optional and default to:state => state
(feed the whole state into props)dispatch => ({ dispatch })
(feed the dispatcher into props)
Caveats:
- Stateful components? Hmmm...
This is also available as a root export (in that case, it takes the redutser as 1st parameter just for type inference).
Redutser#plugShort
Same as plug
, but without the method names.
Typing dispatchers
experimental
(for now) Our react helpers currently use our own dispatcher types (instead of the sugested redux ones), declared globally as Redutser.DispatchInput
. You may manually augment them (though declaration merging) in order to add additional middleware signatures. For instance, in order to add the thunk signature, write:
declare global
Composition helpers
subdomain ( "extends" Redutser )
Glues other redutser
s for a bigger purpose, creating a compound redutser. They are expected to share the same state type.
Action types from the sources are composed into the payload
parameter.
Supplied action creators go one level deeper:
store.dispatchmeatBall.creators.red2.world
liftRedutserState( initialOuterState, key: string, innerRedutser ) : redutser
This is an utility which "moves up" the state of the innerRedutser
.
//this will fail since innerA has a different state position//this works
combineRedutsers ( initialOuterState, innerRedutsers ) : redutser
Experimental. Typings may not work.
A shorthand for the example above. The name is on purpose, is "combines" reduTsers
which operate on subsets of the root state.
Known Caveats
- When actions have no parameters, you will still be required to pass an empty object
{}
to the payload. - (Redux) If using redux 3.x, you might want to disable
strictFunctionTypes
compiler options (thats a general redux+ts issue).4.x
typings work great and are highly recommended.
Using this
on createRedutser
Typescript has inference issues when using this
on createReducer ( issue ). You may choose a new "curried" alternate version of the function: createRedutser2(initialState)({ ...reducer })
which
works better with the inference.
Building
Check the npm scripts.
Code style: Run prettier with the included config and we're good.