Package Exports
- fully-typed-actions
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (fully-typed-actions) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Fully Typed Actions
Helpers for fully typed redux action creators with Typescript >=v2.8. Also features an Epic ofType rxjs operator.
This package is heavily inspired from Martin Hochel and the code is taken from his article: Improved Redux type safety with TypeScript 2.8
Getting Started
Install fully-typed-actions:
npm install fully-typed-actionsyarn add fully-typed-actionsUsage In Actions
import { ActionsUnion, createAction } from 'fully-typed-actions';
export const SET_AGE = '[core] set age';
export const SET_NAME = '[core] set name';
export const RELOAD_URL = '[router] Reload Page';
export const Actions = {
setAge: (age: number) => createAction(SET_AGE, age),
setName: (name: string) => createAction(SET_NAME, name),
reloadUrl: () => createAction(RELOAD_URL),
};
export type Actions = ActionsUnion<typeof Actions>;Usage In Reducers
import * as fromActions from './actions'
export interface State {
user: { age: number; name: string } | {}
reloadPage: boolean
}
export const initialState: State = {
user: {},
reloadPage: false,
}
export const reducer = (state = initialState, action: fromActions.Actions): State => {
switch (action.type) {
case fromActions.SET_AGE: {
const { payload: newAge } = action
state.user
const newUser = { ...state.user, age: newAge }
const newState = { ...state, user: newUser }
return newState
}
case fromActions.SET_NAME: {
const { payload: newName } = action
const newUser = { ...state.user, age: newName }
const newState = { ...state, user: newUser }
return newState
}
case fromActions.RELOAD_URL: {
// const { type } = action
// const { payload } = action // ERROR
return {
...state,
reloadPage: true,
}
}
default:
return state
}
}Usage In Epics with special ofType operator
import { Epic } from 'redux-observable';
import { map } from 'rxjs/operators';
import { ofType, ActionsOfType } from 'fully-typed-actions';
import { SET_AGE, actions, Actions } from './actions';
import { State } from './store';
// BEHOLD 100% type safe epic ! I ❤️ it !
const epic: Epic<Actions, State> = actions$ => {
return actions$.pipe(
ofType(SET_AGE),
map(action => {
const { type, payload: newAge } = action;
return actions.reloadUrl();
})
);
};Usage In Epics with normal ofType operator from redux-observable
import { Epic, ofType } from 'redux-observable';
import { map } from 'rxjs/operators';
import { ActionsOfType } from 'fully-typed-actions';
import { SET_AGE, actions, Actions } from './actions';
import { State } from './store';
// Extract the action type from the ActionsUnion type
type SetAgeAction = ActionsOfType<Actions, typeof SET_AGE>
const epic: Epic<Actions, State> = actions$ => {
return actions$.pipe(
ofType<Actions, SetAgeAction>(SET_AGE),
map(action => {
const { type, payload: newAge } = action
return Actions.reloadUrl()
})
)
}
const epicWithChainOfType: Epic<Actions, State> = actions$ => {
return actions$.ofType<SetAgeAction>(SET_AGE).pipe(
map(action => {
const { type, payload: newAge } = action
return Actions.reloadUrl()
})
)