diff --git a/src/index.ts b/src/index.ts index d27ce6e..3e66c54 100644 --- a/src/index.ts +++ b/src/index.ts @@ -185,36 +185,54 @@ function createPreparedPromiseAction = PrepareA ); } +interface PromiseActionFactory { + /** + * A utility function to create an action creator for the given action type + * string. The action creator accepts a single argument, which will be included + * in the action object as a field called payload. The action creator function + * will also have its toString() overriden so that it returns the action type, + * allowing it to be used in reducer logic that is looking for that action type. + * The created action contains promise actions to make redux-saga-promise work. + * + * @param type The action type to use for created actions. + */ + create

(type: T): SagaPromiseActionCreator> + /** + * A utility function to create an action creator for the given action type + * string. The action creator accepts a single argument, which will be included + * in the action object as a field called payload. The action creator function + * will also have its toString() overriden so that it returns the action type, + * allowing it to be used in reducer logic that is looking for that action type. + * The created action contains promise actions to make redux-saga-promise work. + * + * @param type The action type to use for created actions. + * @param prepare (optional) a method that takes any number of arguments and returns { payload } or { payload, meta }. + * If this is given, the resulting action creator will pass its arguments to this method to calculate payload & meta. + */ + create = PrepareAction, P = ReturnType["payload"], T extends string = string>(type: T, prepareAction: PA): SagaPromiseActionCreator> +} + /** * @template V Resolve type contraint for promise. */ export function promiseActionFactory() { return { - /** - * A utility function to create an action creator for the given action type - * string. The action creator accepts a single argument, which will be included - * in the action object as a field called payload. The action creator function - * will also have its toString() overriden so that it returns the action type, - * allowing it to be used in reducer logic that is looking for that action type. - * The created action contains promise actions to make redux-saga-promise work. - * - * @param type The action type to use for created actions. - */ - simple:

(type: T) => createPromiseAction(type), - /** - * A utility function to create an action creator for the given action type - * string. The action creator accepts a single argument, which will be included - * in the action object as a field called payload. The action creator function - * will also have its toString() overriden so that it returns the action type, - * allowing it to be used in reducer logic that is looking for that action type. - * The created action contains promise actions to make redux-saga-promise work. - * - * @param type The action type to use for created actions. - * @param prepare (optional) a method that takes any number of arguments and returns { payload } or { payload, meta }. - * If this is given, the resulting action creator will pass its arguments to this method to calculate payload & meta. - */ - advanced: = PrepareAction, T extends string = string>(type: T, prepareAction: PA) => createPreparedPromiseAction(type, prepareAction), - }; + create: (type: any, prepareAction?: any) => { + if (arguments.length === 0) { + throw new ArgumentError("Type was expected"); + } + + if (arguments.length > 2) { + throw new ArgumentError("Too many arguments"); + } + + if (arguments.length === 2) { + return createPreparedPromiseAction(type, prepareAction); + } + + return createPromiseAction(type); + }, + } as any as PromiseActionFactory; } /** diff --git a/test/index.test.ts b/test/index.test.ts index eaea155..c28b9d0 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -17,8 +17,8 @@ import { describe("promiseAction", function () { describe.each([ - promiseActionFactory().simple("simple"), - promiseActionFactory().advanced("prepared", null), + promiseActionFactory().create("simple"), + promiseActionFactory().create("prepared", null), ])("creator", function (actionCreator) { it(`${actionCreator.type} should have keys`, function () { expect(typeof actionCreator?.trigger).toBe("function"); @@ -33,8 +33,8 @@ describe("promiseAction", function () { }); describe.each([ - promiseActionFactory().simple("simple")(), - promiseActionFactory().advanced("prepared", () => ({ payload: { test: "" } }))(), + promiseActionFactory().create("simple")(), + promiseActionFactory().create("prepared", () => ({ payload: { test: "" } }))(), ])("action", function (action) { it(`${action.type} should have keys`, function () { expect(action?.meta?.promiseActions?.resolved).toBeTruthy(); @@ -96,7 +96,7 @@ function setup(saga, { withMiddleware = true } = {}) { // Define the promise action we'll use in our tests. To avoid possible // contamination, create a new one for each test // - const promiseAction = promiseActionFactory().simple("promiseAction"); + const promiseAction = promiseActionFactory().create("promiseAction"); // // Define a reducer that records the payloads of each phase @@ -192,7 +192,7 @@ describe("implementPromiseAction", function () { }); it("should correctly infer value type", function () { - const promiseAction = promiseActionFactory().simple("test"); + const promiseAction = promiseActionFactory().create("test"); call(promiseAction.sagas.implement, promiseAction(), async () => Promise.resolve("")); call(promiseAction.sagas.implement, promiseAction(), function* () { yield "dummy"; return ""; }); call(promiseAction.sagas.implement, promiseAction(), () => ""); @@ -241,7 +241,7 @@ describe("resolvePromiseAction", function () { }); it("should correctly infer value type", function () { - const promiseAction = promiseActionFactory().simple("test"); + const promiseAction = promiseActionFactory().create("test"); call(promiseAction.sagas.resolve, promiseAction(), ""); call(promiseAction.sagas.resolve, promiseAction.trigger(), ""); }); diff --git a/test/index.types.test.ts b/test/index.types.test.ts index aa8ba03..c08a017 100644 --- a/test/index.types.test.ts +++ b/test/index.types.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { promiseActionFactory } from "../src"; -const promiseAction = promiseActionFactory().simple("MY_ACTION"); +const promiseAction = promiseActionFactory().create("MY_ACTION"); declare const typeOfTriggerActionThatGotCreatedFromTheSimpleOrAdvancedActionCreator: typeof promiseAction.types.triggerAction; declare const typeOfResolvedActionThatGotCreatedFromTheSimpleOrAdvancedActionCreator: typeof promiseAction.types.resolvedAction; @@ -13,5 +13,5 @@ interface Payload { data: any } -const mustExpectPayload = promiseActionFactory().simple("MY_ACTION")({ data: {} }); -const mustExpectInferredPayload = promiseActionFactory().advanced("MY_ACTION", (payload: Payload) => ({ payload }))({ data: {} }); +const mustExpectPayload = promiseActionFactory().create("MY_ACTION")({ data: {} }); +const mustExpectInferredPayload = promiseActionFactory().create("MY_ACTION", (payload: Payload) => ({ payload }))({ data: {} });