You're Invited: Meet the Socket team at BSidesSF and RSAC - April 27 - May 1.RSVP
Socket
Sign inDemoInstall
Socket

action-typed

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

action-typed

Better type *safety*, with less actual *typing* for Redux actions

2.0.0
latest
npm
Version published
Weekly downloads
261
-1.51%
Maintainers
1
Weekly downloads
 
Created
Source

Action-typed

Better type-safety, with less actual typing for Redux actions

Install

npm i action-typed
# or
yarn add action-typed

Why

Video walkthrough if you prefer: https://www.youtube.com/watch?v=v263zMyVv6k

  • Maximum type safety from minimal code 👀
  • No need to preload redux with all possible types or use an augmented store from another library - soundness is checked at the point of interaction.
  • All types are derived from the implementation 🧙‍♀️
  • No 'boilerplate', just write a simple JavaScript object and provide provide types for your expected arguments
  • 100% interop with existing Redux middlewares (eg connected routers)
  • Exposes a helper type to convert your raw JavaScript object into a tagged union (discriminated union/algebraic data type)
  • Accurate type narrowing and safety when needed (eg: in reducers)
  • No need to dream up names for action creators, instead just use the type itself to distinguish between actions
  • No need to wrap payloads in {type, payload}s, it feels more like working with type constructors
  • Result/return types of all action creators is inferred from the implementation
  • No need to write separate types - they are all generated at run time and are 100% safe
  • Zero-cost library, adds nothing to your bundle size
  • Action names can be strings/Ennis/consts
  • Namespace your actions however you like (anything that's a valid object key)
  • Get type safety in action creators, components, reducers, thunks, epics or anywhere else - all derived from the same JS object

Example

user.actions.ts

import {ActionHandler, msgCreator} from "action-typed";

// this replaces any action-creators you may have 😍
const messages = {
    SignedIn: (firstname: string, lastname: string) => ({firstname, lastname}),
    Token: (token: string) => token,
    SignOut: () => undefined,
};

export const Msg = msgCreator(messages);
export type Handler = ActionHandler<typeof messages>

index.ts

import {combineReducers, createStore} from "redux";
import {userReducer} from "./user.reducer";
import {Msg} from "./user.actions";

const root = combineReducers({
    user: userReducer
});

const store = createStore(root);

store.dispatch(
    // you can't make a mistake here - the string "SignedIn" is type-safe, and it
    // dictates what the remaining parameters should be 👌
    Msg("SignedIn", "shane", "osbourne")
);

user.reducer.ts

import {Handler} from "./user.actions";

type State = {
    token: string
};

const initialState: State = { token: "" };

//
// this uses the helper union type that's inferred from the JS object
//                                                           ↓
export function userReducer(state = initialState, action: Handler): State { 
    switch (action.type) {
        // matching "Token" here narrows the type of `action`
        // that means you get full type-safety on the value of 'payload' 👌
        case "Token": {
            return { ...state, token: action.payload }
        }
    }
    return state;
}

component example mapDispatchToProps

import React, { Component } from 'react';
import {connect} from "react-redux";
import {Msg} from "./actions/counter.actions";
import {StoreState} from "./configureStore";

type AppProps = {
  Msg: typeof Msg,
  counter: number,
}

class App extends Component<AppProps> {
  render() {
    const {Msg, counter} = this.props;
    return (
      <div className="App">
          {counter}
          <button onClick={() => Msg("Increment")}>Increment</button>
          <button onClick={() => Msg("Decrement", 20)}>Decrement by 20</button>
      </div>
    );
  }
}

export default connect(
    (x: StoreState) => ({ counter: x.counter }),
    // don't map all your separate action-creators here
    {Msg}
)(App);

Keywords

redux

FAQs

Package last updated on 12 May 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts