npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-typed-actions

v0.1.5

Published

An approach to type Redux actions and their payload and statically type checking them in Typescript

Downloads

330

Readme

Redux Typed Actions

An opinionated approach to type actions and their payload in Redux with statically type checking in Typescript. This approach removes the most possible boilerplate of your actions & their creators in React and any other frameworks.

Installation

Let's get started by installing it from npm repository

$ npm install --save-dev redux-typed-actions

or from yarn repository

$ yarn add --dev redux-typed-actions

Usage

Let's do a quick example to see how this approach can improve type checking of redux actions

  1. You have an ItemX interface:
    feature-x.types.ts

    export interface ItemX {
      title: string;
    }
  2. First we define our actions:
    feature-x.actions.ts

    import { defineAction, defineScenarioAction, defineSymbolAction } from 'redux-typed-actions';
    import { ItemX } from './feature-x.types';
    
    // For this action we will have number as our payload
    export const FeatureXAddTicketAction = defineAction<number>('[Feature X] Add Ticket');
    
    /**
     *  This action is special, it's called a scenario-like action
     *  It notifies the system with status of a process covering from start to end.
     *  You can get Start/Success/Failure/Cancel from this action generator/creator
     *  There are 4 types that belong respectively to Start/Success/Failure/Cancel
     *  Note: The default type for payload of success and failure is
     *  string so you can skip them like `defineScenarioAction('MyActionName')`
     */
    export const FeatureXLoadAction = defineScenarioAction<never, ItemX[], string>('[Feature X] Load');
    
    // Let's have a symbol action just for fun
    export const FeatureXDummySymbolAction = defineSymbolAction<ItemX[]>('[Feature X] Dummy Started');

    Note: You can setup your own suffix for Start/Success/Failure/Cancel of scenario actions as following example:

    import { factory } from 'redux-typed-actions';
       
    // You must set them before defining actions
    factory.setSuffixes({
      start: '_REQUEST',
      cancel: '_CANCEL',
      success: '_SUCCESS',
      failure: '_FAILURE',
    });
  3. Now we dispatch our actions:
    feature-x.component.ts

    import { ItemX } from './feature-x.types';
    import { FeatureXAddTicketAction, FeatureXLoadAction } from '../feature-x.actions';
    ...
    
    // React Redux solution to replace action creators:
    // Let's define our component's state
    interface FeatureXProps {
      ...
      addTicket: typeof FeatureXAddTicketAction.strictGet; // StrictGet makes the payload mandatory
    }
    
    ...
    class FeatureX extends React.Component<FeatureXProps> {
      ...
      addTicket = () => this.props.addTicket(1) // <- Static type checking
    
      render() {
        return (<button onClick={this.addTicket}>Add one ticket</button>); // />
      }
    }
    
    // Let's hook the action to redux, and we're done
    export default connect(undefined, { addTicket: FeatureXAddTicketAction.strictGet })(FeatureX);
    
    
    // All Typescript frameworks:
    // Dispatching a simple action
    store.dispatch(FeatureXAddTicketAction.get(100));
    
    // Let's start our scenario by dispatching our action
    store.dispatch(FeatureXLoadAction.get());
    
    // Now we dispatch the success action
    const payload: ItemX[] = [{ title: 'item 1' }, { title: 'item 2' }];
    dispatch(FeatureXLoadAction.success.get(payload));
    
    // or simply a failure
    dispatch(FeatureXLoadAction.failure.get('It failed because...'));
  4. Now let's take a look at our reducers to see how we can type check the payloads:
    feature-x.reducers.ts

    import { PlainAction } from 'redux-typed-actions';
    import { ItemX } from './feature-x.types';
    import { FeatureXLoadAction } from '../feature-x.actions';
    
    export interface ItemXState {
      items: ItemX[];
      loading: boolean;
    }
    
    export function reducer(state: ItemXState = InitialState, action: PlainAction): ItemXState {
      if (FeatureXLoadAction.is(action)) {
        // Within this branch our action variable has the right typings
        return {
          ...state,
          loading: true,
        };
    
      } else if (FeatureXLoadAction.success.is(action)) {
        return {
          ...state,
          loading: false,
          items: action.payload, // <- Here we are checking types strongly
        };
    
      } else {
        return state;
      }
    }
  5. If you're fan of redux-observables then this part is for you:
    feature-x.epics.ts

    (action$, store) => action$
       .ofType(FeatureXLoadAction.type)
       .map(action => FeatureXLoadAction.cast(action)) // <- from here we will have all the typings right :)
       .switchMap(action => Service()
           .map(value => FeatureXLoadAction.success.get(repos))
           .catch(() => Observable.of(FeatureXLoadAction.failure.get('Oops something went wrong!'))));
  6. That's it

Take a look at React or Angular examples for a closer look.