This package has been deprecated

Author message:

Please use redux-ts-utils.

redux-ts-actions
TypeScript icon, indicating that this package has built-in type declarations

1.0.2 • Public • Published

redux-ts-actions

Dependency Status devDependency Status Greenkeeper badge Build Status Npm Version TypeScript 3 License Badges

Type-safe action creators and reducers for redux. Action creators infer input and payload types and reducers infer payload type based on respective action creators. Requires TypeScript 3+.

Example Usage

import {
  createAction,
  handleAction,
  reduceReducers,
} from 'redux-ts-actions';
 
// Action Creators
const setName = createAction('user/SET_NAME', (id: string, name: string) => ({ id, name }));
const incrementFollowers = createAction<string>('user/INCREMENT_FOLLOWERS');
 
// Users Reducer
interface User {
  readonly name: string,
  readonly followers: number,
}
interface State {
  readonly [id: string]: User;
}
 
const initialState: State = {};
const emptyUser: User = { name: '', followers: 0 };
 
const reducer = reduceReducers<State>([
  handleAction(setName, (state, { payload }) => ({
    ...state,
    [payload!.id]: {
      ...(state[payload!.id] || emptyUser),
      name: payload!.name,
    },
  })),
  handleAction(incrementFollowers, (state, { payload }) => ({
    ...state,
    [payload!]: {
      ...(state[payload!] || emptyUser),
      followers: state[payload!].followers + 1,
    },
  })),
], initialState);
 
// Use the reducer:
[setName('id-1', 'Ken'), incrementFollowers('id-1')].reduce(reducer, undefined);

API

createAction

This function creates an action creator. It optionally accepts a payload customizer function. The payload type of the resulting action creator and the arguments the action creator accepts are inferred from the payload creator function.

import { createAction } from 'redux-ts-actions';
 
interface User {
  readonly name: string;
  readonly followers: number;
}
 
// Fully-implicit typing
const createUser = createAction('user/CREATE_USER', (name: string, followers: number) => ({ name, followers }));
createUser('Ken', 15); // Compiles and returns an object with a known shape of { type: 'user/CREATE_USER', payload?: User }
createUser('Ken', false); // Fails to compile. `boolean` is not assignable to `number`.
 
// Identity typing
const createUser = createAction<User>('user/CREATE_USER');
createUser({ name: 'Ken', followers: 15 }); // Compiles and returns the same object as before
createUser({ name: 'Ken', followers: false }); // Fails to compile. `boolean` is not assignable to `number`.
 
// Fully-explicit typing
const createUser = createAction<User, string, number>('user/CREATE_USER', (name, followers) => ({ name, followers }));
createUser('Ken', 15); // Compiles and returns an object with a known shape of { type: 'user/CREATE_USER', payload?: { name, followers }}
createUser('Ken', false); // Fails to compile. `boolean` is not assignable to `number`.
 
// No Payload
const increment = createAction('inc');
increment(); // Creates an action with no payload
 
// Error Handling
// All of the above action creators can accept an Error as their only argument.
// Payload customizers will not be called and the resulting actions will have
// their `error` property set to `true` and their payload will be the error
// object.
createUser(new Error('Foo')); // { type: 'user/CREATE_USER', payload?: Error, error: true }

handleAction

This function creates a type-safe reducer given an action creator and a reducer function. The state argument must be typed (unless this is used in the context of reduceReducers documented below) but the action argument will be inferred based on the action creator.

import { handleAction } from 'redux-ts-actions';
 
const reducer = handleAction(createUser, (state: State, action) => {
  // action.payload is `User | undefined`
});
 
// Or
 
const reducer = handleAction<State>(createUser, (state, action) => {
  // action.payload is `User | undefined`
});

A Note About Flux Standard Actions

The payload property on Flux Standard Actions is optional. In TypeScript you can work with these actions in one of two ways:

const reducer = handleAction(createUser, (state: State, action) => {
  // Method 1:
  if (action.payload) {
    action.payload.name;
  }
  // Method 2:
  action.payload!.name;
});
 
// Method 2 also works with destructuring:
const reducer = handleAction(createUser, (state: State, { payload }) => {
  payload!.name;
});

reduceReducers

This function composes reducers together into a single reducer. It takes an array of reducer functions and an optional default state. If you specify a type then you don't need to specify state types for any child reducers.

import { reduceReducers } from 'redux-ts-actions';
 
const increment = createAction('counter/INCREMENT');
const decrement = createAction('counter/DECREMENT');
const add = createAction<number>('counter/ADD');
 
// Passing a type to `reduceReducers` allows everything below to be typesafe:
 
const reducer = reduceReducers<number>([
  handleAction(inc, i => i + 1),
  handleAction(dec, i => i - 1),
  handleAction(add, (i, { payload = 0 }) => i + payload),
], 0);

License

MIT

Readme

Keywords

Package Sidebar

Install

npm i redux-ts-actions

Weekly Downloads

1

Version

1.0.2

License

MIT

Unpacked Size

75.6 kB

Total Files

79

Last publish

Collaborators

  • knpwrs