0.3.3 • Published 6 years ago

fully-typed-actions v0.3.3

Weekly downloads
6
License
MIT
Repository
github
Last release
6 years ago

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-actions
yarn add fully-typed-actions

Usage 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()
    })
  )