immer-reducer
Advanced tools
Comparing version 0.5.2 to 0.6.0
import { Draft } from "immer"; | ||
/** get function arguments as tuple type */ | ||
declare type ArgumentsType<T> = T extends (...args: infer V) => any ? V : never; | ||
/** | ||
* Get the first value of tuple when the tuple length is 1 otherwise return the | ||
* whole tuple | ||
*/ | ||
declare type FirstOrAll<T> = T extends [infer V] ? V : T; | ||
/** Get union of function property names */ | ||
@@ -45,3 +50,3 @@ declare type FunctionPropertyNames<T> = { | ||
type: ActionTypeType; | ||
payload: Payload; | ||
payload: FirstOrAll<Payload>; | ||
}; | ||
@@ -48,0 +53,0 @@ } |
@@ -91,2 +91,24 @@ "use strict"; | ||
} | ||
/** | ||
* Convert function arguments to ImmerAction object | ||
*/ | ||
function createImmerAction(type, args) { | ||
if (args.length === 1) { | ||
return { type: type, payload: args[0] }; | ||
} | ||
return { | ||
type: type, | ||
payload: args, | ||
args: true, | ||
}; | ||
} | ||
/** | ||
* Get function arguments from the ImmerAction object | ||
*/ | ||
function getArgsFromImmerAction(action) { | ||
if (action.args) { | ||
return action.payload; | ||
} | ||
return [action.payload]; | ||
} | ||
function createActionCreators(immerReducerClass) { | ||
@@ -110,6 +132,3 @@ setCustomNameForDuplicates(immerReducerClass); | ||
} | ||
return { | ||
type: type, | ||
payload: args, | ||
}; | ||
return createImmerAction(type, args); | ||
}; | ||
@@ -140,3 +159,3 @@ actionCreator.type = type; | ||
var reducers = new immerReducerClass(draftState, state); | ||
reducers[methodName].apply(reducers, action.payload); | ||
reducers[methodName].apply(reducers, getArgsFromImmerAction(action)); | ||
return draftState; | ||
@@ -143,0 +162,0 @@ }); |
{ | ||
"name": "immer-reducer", | ||
"version": "0.5.2", | ||
"version": "0.6.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "lib/immer-reducer.js", |
@@ -105,13 +105,8 @@ # immer-reducer | ||
This library by no means requires you to use Typescript but it was written | ||
specifically Typescript usage in mind because I was unable to find any other | ||
libraries that make Redux usage both terse and 100% type safe. | ||
The generated `ActionCreator` object respect the types used in the class | ||
The generated `ActionsTypes` object respect the types used in the class | ||
```ts | ||
const action = ActionCreators.setFirstName("Charlie"); // OK | ||
action.payload[0]; // OK string type | ||
const action = ActionCreators.setFirstName("Charlie"); | ||
action.payload; // Has the type of string | ||
action.payload[1]; // Type error. Only one argument. | ||
ActionCreators.setFirstName(1); // Type error. Needs string. | ||
@@ -121,2 +116,11 @@ ActionCreators.setWAT("Charlie"); // Type error. Unknown method | ||
If the reducer class where to have a method which takes more than one argument | ||
the payload would be array of the arguments | ||
```ts | ||
// setName(firstName: string, lastName: string) {} | ||
const action = ActionCreators.setName("Charlie", "Brown"); | ||
action.payload; // will have value ["charlie", "brown"] and type [string, string] | ||
``` | ||
The reducer function is also typed properly | ||
@@ -139,17 +143,23 @@ | ||
type: "IMMER_REDUCER:MyImmerReducer#setFirstName", | ||
payload: ["Charlie"], | ||
payload: "Charlie", | ||
} | ||
{ | ||
type: "IMMER_REDUCER:MyImmerReducer#setLastName", | ||
payload: ["Brown"], | ||
payload: "Brown", | ||
} | ||
{ | ||
type: "IMMER_REDUCER:MyImmerReducer#setName", | ||
payload: ["Charlie", "Brown"], | ||
args: true | ||
} | ||
``` | ||
So the method names become the Redux Action Types and the method arguments | ||
become the action payloads. The reducer function will then match these | ||
actions against the class and calls the appropriate methods with the payload | ||
array spread to the arguments. But do note that the action format is not part | ||
of the public API so don't write any code relying on it. The actions are | ||
handled by the generated reducer function. | ||
So the class and method names become the Redux Action Types and the method | ||
arguments become the action payloads. The reducer function will then match | ||
these actions against the class and calls the appropriate methods with the | ||
payload array spread to the arguments. | ||
🚫 The format of the `action.type` string is internal to immer-reducer. If | ||
you need to detect the actions use the provided type guards. | ||
The generated reducer function executes the methods inside the `produce()` | ||
@@ -166,3 +176,3 @@ function of Immer enabling the terse mutatable style updates. | ||
In redux-observable | ||
With redux-observable | ||
@@ -181,3 +191,3 @@ ```ts | ||
// action.payload - recognized as string | ||
map(action => action.payload[0].toUpperCase()), | ||
map(action => action.payload.toUpperCase()), | ||
... | ||
@@ -187,3 +197,3 @@ ); | ||
In redux-saga | ||
With redux-saga | ||
@@ -235,6 +245,6 @@ ```ts | ||
// type: "setFirstName"; | ||
// payload: [string]; | ||
// payload: string; | ||
// } | { | ||
// type: "setLastName"; | ||
// payload: [string]; | ||
// payload: string; | ||
// }; | ||
@@ -252,4 +262,3 @@ } | ||
if (isAction(someAction, ActionCreators.setFirstName)) { | ||
someAction.type; // Type checks to `"setFirstName"` | ||
someAction.payload; // Type checks `[string]` | ||
someAction.payload; // Type checks to `string` | ||
} | ||
@@ -271,7 +280,7 @@ ``` | ||
type: "setFirstName"; | ||
payload: [string]; | ||
payload: string; | ||
} | ||
| { | ||
type: "setLastName"; | ||
payload: [string]; | ||
payload: string; | ||
}; | ||
@@ -278,0 +287,0 @@ ``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23041
260
290