You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* improved redux section text and examples
updated tslint to strict for 2.6 and future new strict features
* review fixes
* updated deps
* closes#6
* updated TOC
* final touches
Copy file name to clipboardExpand all lines: docs/markdown/1_react.md
+14Lines changed: 14 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -134,6 +134,20 @@ Adds error handling using componentDidCatch to any component
134
134
135
135
## Redux Connected Components
136
136
137
+
### Caveat with `bindActionCreators`
138
+
**If you try to use `connect` or `bindActionCreators` explicitly and want to type your component callback props as `() =>void` this will raise compiler errors. I happens because `bindActionCreators` typings will not map the return type of action creators to `void`, due to a current TypeScript limitations.**
139
+
140
+
A decent alternative I can recommend is to use `() =>any` type, it will work just fine in all possible scenarios and should not cause any typing problems whatsoever. All the code examples in the Guide with `connect` are also using this pattern.
141
+
142
+
> If there is any progress or fix in regard to the above caveat I'll update the guide and make an announcement on my twitter/medium (There are a few existing proposals already).
143
+
144
+
> There is alternative way to retain type soundness but it requires an explicit wrapping with `dispatch` and will be very tedious for the long run. See example below:
This pattern is focused on a KISS principle - to stay clear of complex proprietary abstractions and follow simple and familiar JavaScript const based types:
5
+
> Using Typesafe Action Creators helpers for Redux [`typesafe-actions`](https://github.com/piotrwitek/typesafe-actions)
7
6
8
-
Advantages:
9
-
- simple "const" based types
10
-
- familiar to standard JS usage
11
-
12
-
Disadvantages:
13
-
- significant amount of boilerplate and duplication
14
-
- necessary to export both action types and action creators to re-use in other places, e.g. `redux-saga` or `redux-observable`
7
+
A recommended approach is to use a simple functional helper to automate the creation of type-safe action creators. The advantage is that we can reduce a lot of code repetition and also minimize surface of errors by using type-checked API.
8
+
> There are more specialized functional helpers available that will help you to further reduce tedious boilerplate and type-annotations in common scenarios like reducers (`getType`) or epics (`isActionOf`).
9
+
All that without losing type-safety! Please check this very short [Tutorial](https://github.com/piotrwitek/typesafe-actions#tutorial)
In a DRY approach, we're introducing a simple factory function to automate the creation process of type-safe action creators. The advantage here is that we can reduce boilerplate and repetition significantly. It is also easier to re-use action creators in other layers thanks to `getType` helper function returning "type constant".
23
-
24
-
Advantages:
25
-
- using factory function to automate creation of type-safe action creators
26
-
- less boilerplate and code repetition than KISS Style
27
-
- getType helper to obtain action creator type (this makes using "type constants" unnecessary)
-[Discriminated Union types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
60
-
-[Mapped types](https://www.typescriptlang.org/docs/handbook/advanced-types.html) e.g. `Readonly` & `Partial`
61
19
62
-
### Tutorial
63
-
Declare reducer `State` type definition with readonly modifier for `type level` immutability
20
+
### State with Type-level Immutability
21
+
Declare reducer `State` type with `readonly` modifier to get "type level" immutability
64
22
```ts
65
23
exporttypeState= {
66
24
readonly counter:number,
67
25
};
68
26
```
69
27
70
-
Readonly modifier allow initialization, but will not allow rassignment highlighting an error
28
+
Readonly modifier allow initialization, but will not allow rassignment by highlighting compiler errors
71
29
```ts
72
30
exportconst initialState:State= {
73
31
counter: 0,
@@ -76,69 +34,51 @@ export const initialState: State = {
76
34
initialState.counter=3; // Error, cannot be mutated
77
35
```
78
36
79
-
#### Caveat: Readonly does not provide recursive immutability on objects
80
-
> This means that readonly modifier does not propagate immutability on nested properties of objects or arrays of objects. You'll need to set it explicitly on each nested property.
37
+
#### Caveat: Readonly does not provide a recursive immutability on objects
38
+
This means that the `readonly` modifier doesn't propagate immutability down to "properties" of objects. You'll need to set it explicitly on each nested property that you want.
81
39
40
+
Check the example below:
82
41
```ts
83
42
exporttypeState= {
84
-
readonlycounterContainer: {
85
-
readonlyreadonlyCounter:number,
86
-
mutableCounter:number,
43
+
readonlycontainerObject: {
44
+
readonlyimmutableProp:number,
45
+
mutableProp:number,
87
46
}
88
47
};
89
48
90
-
state.counterContainer= { mutableCounter: 1 }; // Error, cannot be mutated
91
-
state.counterContainer.readonlyCounter=1; // Error, cannot be mutated
49
+
state.containerObject= { mutableProp: 1 }; // Error, cannot be mutated
50
+
state.containerObject.immutableProp=1; // Error, cannot be mutated
92
51
93
-
state.counterContainer.mutableCounter=1; // No error, can be mutated
52
+
state.containerObject.mutableProp=1; // OK! No error, can be mutated
94
53
```
95
54
96
-
> There are few utilities to help you achieve nested immutability. e.g. you can do it quite easily by using convenient `Readonly` or `ReadonlyArray` mapped types.
55
+
#### Best-practices for nested immutability
56
+
> use `Readonly` or `ReadonlyArray`[Mapped types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
state.counterPairs[0].immutableCounter1=1; // Error, cannot be mutated
68
+
state.counterPairs[0].immutableCounter2=1; // Error, cannot be mutated
109
69
```
110
70
111
-
> _There are some experiments in the community to make a `ReadonlyRecursive` mapped type, but I'll need to investigate if they really works_
71
+
> _There are some experiments in the community to make a `ReadonlyRecursive` mapped type. I'll update this section of the guide as soon as they are stable_
112
72
113
73
[⇧ back to top](#table-of-contents)
114
74
115
-
### Examples
116
-
117
-
#### Reducer with classic `const types`
75
+
### Reducer Example
76
+
> using `getType` helper and [Discriminated Union types](https://www.typescriptlang.org/docs/handbook/advanced-types.html)
This pattern is focused on a KISS principle - to stay clear of abstractions and to follow a more complex but familiar JavaScript "const" based approach:
158
+
159
+
Advantages:
160
+
- familiar to standard JS "const" based approach
161
+
162
+
Disadvantages:
163
+
- significant amount of boilerplate and duplication
164
+
- more complex compared to `createAction` helper library
165
+
- necessary to export both action types and action creators to re-use in other places, e.g. `redux-saga` or `redux-observable`
0 commit comments