{"id":16384026,"url":"https://github.com/lttb/typed-actions","last_synced_at":"2025-10-05T20:27:11.503Z","repository":{"id":29357536,"uuid":"120899021","full_name":"lttb/typed-actions","owner":"lttb","description":"Type-safe redux-actions","archived":false,"fork":false,"pushed_at":"2023-10-17T10:46:58.000Z","size":1659,"stargazers_count":42,"open_issues_count":1,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-01T20:49:03.544Z","etag":null,"topics":["flowtype","redux","redux-actions","redux-observable"],"latest_commit_sha":null,"homepage":"https://npm.im/typed-actions","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lttb.png","metadata":{"files":{"readme":"README.MD","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-02-09T11:44:30.000Z","updated_at":"2024-05-15T17:48:07.000Z","dependencies_parsed_at":"2023-02-18T19:46:03.215Z","dependency_job_id":"717f85b0-c026-4bfc-b124-24cc91127295","html_url":"https://github.com/lttb/typed-actions","commit_stats":{"total_commits":112,"total_committers":5,"mean_commits":22.4,"dds":0.25,"last_synced_commit":"d0069fd5f215cc6a1adb393959b74ee4da2b0d29"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lttb%2Ftyped-actions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lttb%2Ftyped-actions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lttb%2Ftyped-actions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lttb%2Ftyped-actions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lttb","download_url":"https://codeload.github.com/lttb/typed-actions/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243822283,"owners_count":20353499,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flowtype","redux","redux-actions","redux-observable"],"created_at":"2024-10-11T04:10:20.097Z","updated_at":"2025-10-05T20:27:06.441Z","avatar_url":"https://github.com/lttb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# typed-actions\n\n[![Travis branch](https://img.shields.io/travis/lttb/typed-actions/master.svg?style=flat)](https://travis-ci.org/lttb/typed-actions)\n[![npm version](https://img.shields.io/npm/v/typed-actions.svg?style=flat)](https://www.npmjs.com/package/typed-actions)\n[![npm license](https://img.shields.io/npm/l/typed-actions.svg?style=flat)](https://www.npmjs.com/package/typed-actions)\n\n\nSome Types and Utils (based on [redux-actions](https://github.com/reduxactions/redux-actions) way) to create type-safe actions, reducers, and epics with auto-inferred types.\n\n**Main points**:\n- 100% Flow coverage for the redux-side with minimum typings (auto-inferred types) and less boilerplate\n- Safe types and functions, which help to reduce risks for Type mistakes\n- Accurate Type-errors handling\n- Deep immutable Type (`Frozen`) for actions and redux state\n- [Immer](https://github.com/mweststrate/immer) support\n\n## Installation\n\n```sh\nnpm install typed-actions\n```\n\n## Usage\n\n\u003e You can get some examples [here](https://github.com/lttb/typed-actions/tree/master/src/tests) with explanations.\n\n- [Actions](#actions)\n- [Reducers](#reducers)\n  - [Immer](#immer)\n- [Epics](#epics)\n\n### Actions\nActions are compatible with [Flux Standard Action](https://github.com/redux-utilities/flux-standard-action)\n\n- `action(payload, ?meta)` produces `{type, payload} | {type, payload, meta}`\n- `error(payload, ?meta)` produces `{type, payload, error: true} | {type, payload, meta, error: true}`\n- `empty()` produces `{type}`\n\n\n```js\nimport {createActions, action, empty} from 'typed-actions'\nimport type {EntityId} from '../types';\n\n/**\n * Declare Action Types as constants and export them\n */\nexport const UPDATE = '@namespace/UPDATE'\nexport const UPDATE_FULFILLED = '@namespace/UPDATE_FULFILLED'\nexport const UPDATE_FAILED = '@namespace/UPDATE_FAILED'\n\n/**\n * Create Actions Collection\n */\nconst actions = createActions({\n    /**\n     * {type: UPDATE}\n     */\n    [UPDATE]: empty,\n    /**\n     * {type: UPDATE_FULFILLED, payload: EntityId[]}\n     */\n    [UPDATE_FULFILLED]: (x: EntityId[]) =\u003e action(x),\n    /**\n     * {type: UPDATE_FAILED, payload: EntityId, meta: {sync: true}}\n     */\n    [UPDATE_FAILED]: (x: EntityId) =\u003e action(x, {sync: true}),\n})\n\n/**\n * Export Action Creators\n */\nexport const {\n    [UPDATE]: update,\n    [UPDATE_FULFILLED]: updateFulfilled,\n    [UPDATE_FAILED]: updateFailed,\n} = actions\n\n/**\n * Export Collection Type\n */\nexport type Actions = typeof actions\n```\n\nYou might find this declaration style more readable:\n\n```js\nlet actions\n\nexport const {\n    [UPDATE]: update,\n    [UPDATE_FULFILLED]: updateFulfilled,\n    [UPDATE_FAILED]: updateFailed,\n} = actions = createActions({\n    [UPDATE]: empty,\n    [UPDATE_FULFILLED]: (x: EntityId[]) =\u003e action(x)\n    [UPDATE_FAILED]: (x: EntityId) =\u003e action(x, {sync: true}),\n})\n\nexport type Actions = typeof actions\n```\n\n### Reducers\n\n```js\nimport {handleActions, type Handlers, type Frozen} from 'typed-actions';\nimport type {EntityId} from '../types';\n\n/**\n * Import action types with Actions Collection Type\n */\nimport {\n    type Actions,\n    UPDATE,\n    UPDATE_FULFILLED,\n    UPDATE_FAILED,\n} from './actions';\n\n/**\n * Declare State for the reducer\n */\nexport type State = {\n    data: EntityId[],\n    status: 'done' | 'pending' | 'failed',\n};\n\n/**\n * Use Handlers Type for the type-casting.\n * This way functions will get right arguments Types\n */\nexport default handleActions(({\n    /**\n     * No need to point the State Type in arguments,\n     * it would be auto-inferred Deep Immutable Type of State\n     */\n    [UPDATE]: state =\u003e ({\n        ...state,\n        status: 'pending',\n    }),\n\n    /**\n     * The second argument (action) will also have the right type\n     * {type: UPDATE_FULFILLED, payload: EntityId[]}\n     */\n    [UPDATE_FULFILLED]: (state, {payload}) =\u003e ({\n        ...state,\n        data: payload,\n        status: 'done',\n    }),\n\n    [UPDATE_FAILED]: state =\u003e ({\n        ...state,\n        status: 'failed',\n    }),\n}: Handlers\u003cState, Actions\u003e));\n```\n\n#### Immer\n\nYou can use [immer](https://github.com/mweststrate/immer) for immutable state modifying.\n\n\u003e Note that `handler` accepts 3 arguments: `draft state` (for changes), `action` and `current state`.\n\n```js\nimport { type Handlers, handleActions } from 'typed-actions/immer'\nimport type {EntityId} from '../types';\n\nimport {\n    type Actions,\n    UPDATE,\n    UPDATE_FULFILLED,\n    UPDATE_FAILED,\n} from './actions';\n\nexport type State = {\n    data: EntityId[],\n    status: 'done' | 'pending' | 'failed',\n};\n\nexport default handleActions(({\n    [UPDATE]: state =\u003e {\n        state.status = 'pending'\n    },\n\n    [UPDATE_FULFILLED]: (state, {payload}) =\u003e {\n        state.data = payload\n        state.status = 'done'\n    },\n\n    [UPDATE_FAILED]: state =\u003e {\n        state.status = 'failed'\n    },\n}: Handlers\u003cState, Actions\u003e));\n```\n\n### Epics\n\nIf you're using [redux-observable](https://github.com/redux-observable/redux-observable), this Epic Type could be useful.\n\n```js\nimport type {Epic} from 'typed-actions/redux-observable';\n\nimport {\n    type Actions,\n    UPDATE_FULFILLED,\n    anotherOneAction,\n} from './actions';\n\nimport {type State} from './reducers';\n\nexport const updateEpic: Epic\u003cState, Actions\u003e = action$ =\u003e action$\n    .ofType(UPDATE_FULFILLED)\n    /**\n     * No need to add types here, action would be the right Type out of the box\n     */\n    .map(action =\u003e anotherOneAction(action.payload));\n\nexport const unionEpic: Epic\u003cState, Actions\u003e = action$ =\u003e action$\n    .ofType(UPDATE, UPDATE_FULFILLED)\n    /**\n     * {type: UPDATE} | {type: UPDATE_FULFILLED, payload: EntityId[]}\n     */\n    .map(action =\u003e {\n        if (action.type === UPDATE_FULFILLED) {\n            /**\n             * Type Refinement will work as well\n             *\n             * {type: UPDATE_FULFILLED, payload: EntityId[]}\n             */\n            console.log(action.payload)\n        }\n    });\n```\n\nJust to note, if you're using `dependencies` in epics, you can pass its type in as the third argument.\n\n```js\ntype Dependencies = {api: () =\u003e void}\n\nexport const epic: Epic\u003cState, Actions, Dependencies\u003e = action$ =\u003e action$\n```\n\nThe recommended way is to redeclare your own `Epic` type with custom dependencies and use it, like:\n\n```js\n// types.js\nimport type {Epic} from 'typed-actions/redux-observable'\n\ntype Dependencies = {api: () =\u003e void}\n\nexport type Epic\u003cS, A, D = Dependencies\u003e = Epic\u003cS, A, D\u003e\n\n// epics.js\nimport type {Epic} from './types'\n\nexport const epic: Epic\u003cState, Actions\u003e = action$ =\u003e action$\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flttb%2Ftyped-actions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flttb%2Ftyped-actions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flttb%2Ftyped-actions/lists"}