JSPM

fully-typed-actions

0.3.3
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q23048F
  • License MIT

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