Skip to content

Commit 3f978be

Browse files
authored
Added new solution to Connect with react-redux to solve validation of action creators with bindActionCreators (piotrwitek#157)
1 parent e732b43 commit 3f978be

File tree

2 files changed

+52
-22
lines changed

2 files changed

+52
-22
lines changed

README.md

+26-11
Original file line numberDiff line numberDiff line change
@@ -1427,42 +1427,57 @@ export const getFilteredTodos = createSelector(getTodos, getTodosFilter, (todos,
14271427
14281428
## Connect with `react-redux`
14291429
1430+
### Typing connected component
1431+
14301432
*__NOTE__: Below you'll find only a short explanation of concepts behind typing `connect`. For more real-world examples please check [Redux Connected Components](#redux-connected-components) section.*
14311433
14321434
```tsx
14331435
import MyTypes from 'MyTypes';
14341436

1435-
import { bindActionCreators, Dispatch } from 'redux';
1437+
import { bindActionCreators, Dispatch, ActionCreatorsMapObject } from 'redux';
14361438
import { connect } from 'react-redux';
14371439

14381440
import { countersActions } from '../features/counters';
14391441
import { FCCounter } from '../components';
14401442

1441-
// `state` argument annotation is mandatory to check the correct shape of a state object and injected props
1442-
// you can also extend connected component Props type by annotating `ownProps` argument
1443+
// Type annotation for "state" argument is mandatory to check
1444+
// the correct shape of state object and injected props you can also
1445+
// extend connected component Props interface by annotating `ownProps` argument
14431446
const mapStateToProps = (state: MyTypes.RootState, ownProps: FCCounterProps) => ({
14441447
count: state.counters.reduxCounter,
14451448
});
14461449

1447-
// `dispatch` argument needs an annotation to check the correct shape of an action object
1448-
// when using dispatch function
1449-
const mapDispatchToProps = (dispatch: Dispatch<MyTypes.RootAction>) => bindActionCreators({
1450-
onIncrement: countersActions.increment,
1451-
}, dispatch);
1450+
// "dispatch" argument needs an annotation to check the correct shape
1451+
// of an action object when using dispatch function
1452+
const mapDispatchToProps = (dispatch: Dispatch<MyTypes.RootAction>) =>
1453+
bindActionCreators({
1454+
onIncrement: countersActions.increment,
1455+
}, dispatch);
14521456

14531457
// shorter alternative is to use an object instead of mapDispatchToProps function
14541458
const dispatchToProps = {
14551459
onIncrement: countersActions.increment,
14561460
};
14571461

1458-
// Notice ee don't need to pass any generic type parameters to neither connect nor map functions above
1462+
// Notice we don't need to pass any generic type parameters to neither
1463+
// the connect function below nor map functions declared above
14591464
// because type inference will infer types from arguments annotations automatically
1460-
// It's much cleaner and idiomatic approach
1465+
// This is much cleaner and idiomatic approach
14611466
export const FCCounterConnected =
14621467
connect(mapStateToProps, mapDispatchToProps)(FCCounter);
1468+
1469+
// You can add extra layer of validation of your action creators
1470+
// by using bindActionCreators generic type parameter and RootAction type
1471+
const mapDispatchToProps = (dispatch: Dispatch<MyTypes.RootAction>) =>
1472+
bindActionCreators<ActionCreatorsMapObject<Types.RootAction>>({
1473+
invalidActionCreator: () => 1, // Error: Type 'number' is not assignable to type '{ type: "todos/ADD"; payload: Todo; } | { ... }
1474+
}, dispatch);
1475+
14631476
```
14641477
1465-
*__NOTE__ (for `redux-thunk`): When using thunk action creators you need to use `bindActionCreators`. Only this way you can get corrected dispatch props type signature like below.*
1478+
### Typing connected component using `redux-thunk` action creators
1479+
1480+
*__NOTE__: When using thunk action creators you need to use `bindActionCreators`. Only this way you can get corrected dispatch props type signature like below.*
14661481
14671482
*__WARNING__: As of now (Apr 2019) `bindActionCreators` signature of the latest `redux-thunk` release will not work as below, you need to use updated type definitions that you can find here [`/playground/typings/redux-thunk/index.d.ts`](./playground/typings/redux-thunk/index.d.ts) and then add `paths` overload in your tsconfig like this: [`"paths":{"redux-thunk":["typings/redux-thunk"]}`](./playground/tsconfig.json).*
14681483

README_SOURCE.md

+26-11
Original file line numberDiff line numberDiff line change
@@ -496,42 +496,57 @@ state.containerObject.numbers.push(1); // TS Error: cannot use mutator methods
496496
497497
## Connect with `react-redux`
498498
499+
### Typing connected component
500+
499501
*__NOTE__: Below you'll find only a short explanation of concepts behind typing `connect`. For more real-world examples please check [Redux Connected Components](#redux-connected-components) section.*
500502
501503
```tsx
502504
import MyTypes from 'MyTypes';
503505

504-
import { bindActionCreators, Dispatch } from 'redux';
506+
import { bindActionCreators, Dispatch, ActionCreatorsMapObject } from 'redux';
505507
import { connect } from 'react-redux';
506508

507509
import { countersActions } from '../features/counters';
508510
import { FCCounter } from '../components';
509511

510-
// `state` argument annotation is mandatory to check the correct shape of a state object and injected props
511-
// you can also extend connected component Props type by annotating `ownProps` argument
512+
// Type annotation for "state" argument is mandatory to check
513+
// the correct shape of state object and injected props you can also
514+
// extend connected component Props interface by annotating `ownProps` argument
512515
const mapStateToProps = (state: MyTypes.RootState, ownProps: FCCounterProps) => ({
513516
count: state.counters.reduxCounter,
514517
});
515518

516-
// `dispatch` argument needs an annotation to check the correct shape of an action object
517-
// when using dispatch function
518-
const mapDispatchToProps = (dispatch: Dispatch<MyTypes.RootAction>) => bindActionCreators({
519-
onIncrement: countersActions.increment,
520-
}, dispatch);
519+
// "dispatch" argument needs an annotation to check the correct shape
520+
// of an action object when using dispatch function
521+
const mapDispatchToProps = (dispatch: Dispatch<MyTypes.RootAction>) =>
522+
bindActionCreators({
523+
onIncrement: countersActions.increment,
524+
}, dispatch);
521525

522526
// shorter alternative is to use an object instead of mapDispatchToProps function
523527
const dispatchToProps = {
524528
onIncrement: countersActions.increment,
525529
};
526530

527-
// Notice ee don't need to pass any generic type parameters to neither connect nor map functions above
531+
// Notice we don't need to pass any generic type parameters to neither
532+
// the connect function below nor map functions declared above
528533
// because type inference will infer types from arguments annotations automatically
529-
// It's much cleaner and idiomatic approach
534+
// This is much cleaner and idiomatic approach
530535
export const FCCounterConnected =
531536
connect(mapStateToProps, mapDispatchToProps)(FCCounter);
537+
538+
// You can add extra layer of validation of your action creators
539+
// by using bindActionCreators generic type parameter and RootAction type
540+
const mapDispatchToProps = (dispatch: Dispatch<MyTypes.RootAction>) =>
541+
bindActionCreators<ActionCreatorsMapObject<Types.RootAction>>({
542+
invalidActionCreator: () => 1, // Error: Type 'number' is not assignable to type '{ type: "todos/ADD"; payload: Todo; } | { ... }
543+
}, dispatch);
544+
532545
```
533546
534-
*__NOTE__ (for `redux-thunk`): When using thunk action creators you need to use `bindActionCreators`. Only this way you can get corrected dispatch props type signature like below.*
547+
### Typing connected component using `redux-thunk` action creators
548+
549+
*__NOTE__: When using thunk action creators you need to use `bindActionCreators`. Only this way you can get corrected dispatch props type signature like below.*
535550
536551
*__WARNING__: As of now (Apr 2019) `bindActionCreators` signature of the latest `redux-thunk` release will not work as below, you need to use updated type definitions that you can find here [`/playground/typings/redux-thunk/index.d.ts`](./playground/typings/redux-thunk/index.d.ts) and then add `paths` overload in your tsconfig like this: [`"paths":{"redux-thunk":["typings/redux-thunk"]}`](./playground/tsconfig.json).*
537552

0 commit comments

Comments
 (0)