Skip to content

Commit

Permalink
Optional action payload
Browse files Browse the repository at this point in the history
  • Loading branch information
Vanuan committed Feb 12, 2020
1 parent fbbd7ff commit 3d80f8e
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 70 deletions.
55 changes: 48 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export interface AnyAction {

export type Meta = null | {[key: string]: any};

export interface Action<Payload> extends AnyAction {
interface Action<Payload> extends AnyAction {
type: string;
payload: Payload;
error?: boolean;
Expand Down Expand Up @@ -32,7 +32,7 @@ export function isType<Payload>(
return action.type === actionCreator.type;
}

export interface ActionCreator<Payload> {
interface ActionCreatorWithPayload<Payload> {
type: string;
/**
* Identical to `isType` except it is exposed as a bound method of an action
Expand Down Expand Up @@ -70,14 +70,55 @@ export interface ActionCreator<Payload> {
(payload: Payload, meta?: Meta): Action<Payload>;
}

interface ActionCreatorWithoutPayload<Payload> {
type: string;
/**
* Identical to `isType` except it is exposed as a bound method of an action
* creator. Since it is bound and takes a single argument it is ideal for
* passing to a filtering function like `Array.prototype.filter` or
* RxJS's `Observable.prototype.filter`.
*
* @example
*
* const somethingHappened =
* actionCreator<{foo: string}>('SOMETHING_HAPPENED');
* const somethingElseHappened =
* actionCreator<{bar: number}>('SOMETHING_ELSE_HAPPENED');
*
* if (somethingHappened.match(action)) {
* // action.payload has type {foo: string}
* }
*
* const actionArray = [
* somethingHappened({foo: 'foo'}),
* somethingElseHappened({bar: 5}),
* ];
*
* // somethingHappenedArray has inferred type Action<{foo: string}>[]
* const somethingHappenedArray =
* actionArray.filter(somethingHappened.match);
*/
match: (action: AnyAction) => action is Action<Payload>;
/**
* Creates action without payload.
*
*/
(): Action<Payload>;
}

export type ActionCreator<Payload> =
Payload extends void
? ActionCreatorWithoutPayload<Payload> & ActionCreatorWithPayload<Payload>
: ActionCreatorWithPayload<Payload>;

export type Success<Params, Result> = (
| {params: Params}
| (Params extends void ? {params?: Params} : never)) &
({result: Result} | (Result extends void ? {result?: Result} : never));
(Params extends void ? {params?: Params} : {params: Params})) &
(Result extends void ? {result?: Result} : {result: Result});

export type Failure<Params, Error> = (
| {params: Params}
| (Params extends void ? {params?: Params} : never)) & {error: Error};
(Params extends void
? {params?: Params}
: {params: Params})) & {error: Error};

export interface AsyncActionCreators<Params, Result, Error = {}> {
type: string;
Expand Down
6 changes: 6 additions & 0 deletions tests/typings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const actionCreator = actionCreatorFactory();
function testPayload() {
const withPayload = actionCreator<{foo: string}>('WITH_PAYLOAD');
const withoutPayload = actionCreator('WITHOUT_PAYLOAD');
const withOrWithoutPayload = actionCreator<string | undefined>('WITH_ORWITHOUT_PAYLOAD')

// typings:expect-error
const a = withPayload();
Expand All @@ -21,6 +22,11 @@ function testPayload() {
const f = withoutPayload(undefined, {meta: 'meta'});
// typings:expect-error
const g = withoutPayload({foo: 'bar'});

const h = withOrWithoutPayload('string');
//const i = withOrWithoutPayload();
// typings:expect-error
const j = withOrWithoutPayload(111);
}

function testAsyncPayload() {
Expand Down
92 changes: 29 additions & 63 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"

ansi-styles@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
dependencies:
color-convert "^1.9.0"
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==

arr-diff@^2.0.0:
version "2.0.0"
Expand All @@ -47,10 +46,6 @@ array-unique@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53"

arrify@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"

babel-code-frame@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
Expand Down Expand Up @@ -92,24 +87,6 @@ chalk@^1.1.0:
strip-ansi "^3.0.0"
supports-color "^2.0.0"

chalk@^2.3.0:
version "2.3.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.2.tgz#250dc96b07491bfd601e648d66ddf5f60c7a5c65"
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"

color-convert@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
dependencies:
color-name "^1.1.1"

color-name@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"

colors@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63"
Expand Down Expand Up @@ -143,10 +120,15 @@ defined@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"

diff@^3.1.0, diff@^3.2.0:
diff@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"

diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==

es-abstract@^1.5.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.7.0.tgz#dfade774e01bfcd97f96180298c449c8623fb94c"
Expand All @@ -164,7 +146,7 @@ es-to-primitive@^1.1.1:
is-date-object "^1.0.1"
is-symbol "^1.0.1"

escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
escape-string-regexp@^1.0.2:
version "1.0.5"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"

Expand Down Expand Up @@ -290,10 +272,6 @@ has-ansi@^2.0.0:
dependencies:
ansi-regex "^2.0.0"

has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"

has@^1.0.1, has@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28"
Expand Down Expand Up @@ -441,20 +419,14 @@ micromatch@^2.3.11:
dependencies:
brace-expansion "^1.0.0"

minimist@0.0.8, minimist@~0.0.1:
minimist@~0.0.1:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"

minimist@^1.2.0, minimist@~1.2.0:
minimist@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"

mkdirp@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
dependencies:
minimist "0.0.8"

normalize-path@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
Expand Down Expand Up @@ -598,9 +570,10 @@ semver@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"

source-map-support@^0.5.3:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.6.tgz#4435cee46b1aab62b8e8610ce60f788091c51c13"
source-map-support@^0.5.6:
version "0.5.16"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042"
integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==
dependencies:
buffer-from "^1.0.0"
source-map "^0.6.0"
Expand Down Expand Up @@ -631,12 +604,6 @@ supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"

supports-color@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.3.0.tgz#5b24ac15db80fa927cf5227a4a33fd3c4c7676c0"
dependencies:
has-flag "^3.0.0"

tape@^4.6.2:
version "4.6.3"
resolved "https://registry.yarnpkg.com/tape/-/tape-4.6.3.tgz#637e77581e9ab2ce17577e9bd4ce4f575806d8b6"
Expand All @@ -659,18 +626,16 @@ through@~2.3.4, through@~2.3.8:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"

ts-node@^6.0.0:
version "6.0.3"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-6.0.3.tgz#28bf74bcad134fad17f7469dad04638ece03f0f4"
ts-node@^8.4.0:
version "8.6.2"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.6.2.tgz#7419a01391a818fbafa6f826a33c1a13e9464e35"
integrity sha512-4mZEbofxGqLL2RImpe3zMJukvEvcO1XP8bj8ozBPySdCUXEcU5cIRwR0aM3R+VoZq7iXc8N86NC0FspGRqP4gg==
dependencies:
arrify "^1.0.0"
chalk "^2.3.0"
diff "^3.1.0"
arg "^4.1.0"
diff "^4.0.1"
make-error "^1.1.1"
minimist "^1.2.0"
mkdirp "^0.5.1"
source-map-support "^0.5.3"
yn "^2.0.0"
source-map-support "^0.5.6"
yn "3.1.1"

tslib@^1.6.0:
version "1.7.0"
Expand Down Expand Up @@ -725,6 +690,7 @@ wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"

yn@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/yn/-/yn-2.0.0.tgz#e5adabc8acf408f6385fc76495684c88e6af689a"
[email protected]:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==

0 comments on commit 3d80f8e

Please sign in to comment.