# strong-action

> TypeScript definitions for strongly-typed Redux actions

Latest version **0.1.0** (published 2018-10-19) · MIT license · 0 weekly downloads

> **Deprecated.** This package is deprecated.

## Install

```sh
npm install strong-action
pnpm add strong-action
yarn add strong-action
bun add strong-action
```

## Health

**Score 10/100 (F)** — status: deprecated.

Negative: deprecated.

## Facts

| | |
|---|---|
| Version | 0.1.0 |
| Published | 2018-10-19 |
| First published | 2018-10-19 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 1 |
| Unpacked size | 13.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Chad Norvell |
| Maintainers | chadnorvell |

## Links

- npm: https://www.npmjs.com/package/strong-action
- Repository: https://github.com/chadnorvell/strong-action
- Homepage: https://github.com/chadnorvell/strong-action#readme
- Issues: https://github.com/chadnorvell/strong-action/issues
- npm.io page: https://npm.io/package/strong-action

## Dependencies (1)

- [ts-toolbox](https://npm.io/package/ts-toolbox.md) ^0.1.0

## Recent versions

- 0.1.0 (latest) — 2018-10-19

## README

# strong-action

TypeScript definitions for strongly-typed Redux actions

## Usage

Define your actions as string literals:

```
export const ADD_ITEM = 'ADD_ITEM';
export const DELETE_ITEM = 'DELETE_ITEM';
export const UPDATE_ITEM = 'UPDATE_ITEM';
```

Create an `ActionCreatorsMapObject` (implicitly) by creating an object with keys representing each action and values with action creators that use the included `defineAction` rather than returning the actions directly:

```
export const Actions = {
  addItem: (payload: ItemData) => defineAction(ADD_ITEM, payload),
  deleteItem: (payload: number) => defineAction(DELETE_ITEM, payload),
  updateItem: (payload: Partial<ItemData>) => defineAction(UPDATE_ITEM, payload)
}
```

Then create an `AllActions` type with the same name as your `ActionCreatorsMapObject`. This type will represent the the union of all of the action types:

```
export type Actions = AllActions<typeof Actions>;
```

The value of this setup becomes clear in the reducer. By switching on `action.type`, the TypeScript compiler can infer which action types are valid, and within each action case it will infer the correct payload type:

```
export const reducer = (state = initialState, action: Actions): State => {
  switch(action.type) {
    case ADD_ITEM: {
      // compiler knows that action.payload is ItemData
      return state;
    }
    
    case DELETE_ITEM: {
      // compiler knows that action.payload is number
      return state;
    }
    
    case UPDATE_ITEM: {
      // compiler knows that action.payload is Partial<ItemData>
      return state;
    }
    // the compiler will not let you specify invalid actions, and as long as the
    // reducer's return type is specified and strictNullChecks is enabled, the
    // compiler will also ensure that don't omit any valid actions
  }
}
```

## Rationale

The basic idea is that we want the TypeScript compiler to help us ensure our actions are defined and used consistently, eliminating an entire class of errors. This has been a challenge in the past (without resorting to a class-based solution that doesn't work well with plain Redux), but TypeScript 2.8+ provides features that make it easy.

The naive approach to using TypeScript with Redux actions is to manually create types representing the return types of your action creators, then to actually implement the action creators. This leads to a lot of unwanted repitition and the need to change code in more than one place to change functionality.

An improvement is to generate the action creator return types using the `ReturnType<T>` mapped type on the action creator (the return type of the action creator being the action type). However, since doing so flattens the action's `type` property to a plain string (rather than a string literal), the `type` of the action type has to be explicitly cast to the string literal type in the action creator's returned object. This works but is verbose and a vector for error due to the explicit cast.

The approach used here (implementation described above) produces action creators that preserve their string literal `type` property and generates a union type of all valid actions using type declaration merging.

Once this is done, the actions act as discriminated unions, allowing the compiler to know which actions are valid, invalid, or missing and what payload types are associated with each action in the reducer (or anywhere).

---
_Source: https://npm.io/package/strong-action · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
