diff --git a/README.md b/README.md index 94e9dfc..21e9892 100644 --- a/README.md +++ b/README.md @@ -479,7 +479,7 @@ export const withState =

( } render() { - const { ...remainingProps } = this.props; + const remainingProps = Object.assign({}, this.props); const { count } = this.state; return ( @@ -556,7 +556,7 @@ export const withErrorBoundary =

( } render() { - const { children, ...remainingProps } = this.props; + const { children, ...remainingProps } = this.props as any; const { error } = this.state; if (error) { @@ -958,29 +958,30 @@ describe('Todos Logic', () => { ### Create Root State and Root Action Types #### `RootState` - interface representing redux state tree -Can be imported in connected components to provide type-safety to Redux `connect` function +Can be imported in connected components to provide type-safety to Redux `connect` function. + +Because the RootState is the sum of it's reducers' return types (plus any store Enhancers we may choose to append), TypeScript can infer its shape entirely from Lookup Types and `ReturnType<>`. ```tsx import { combineReducers } from 'redux'; -import { routerReducer, RouterState } from 'react-router-redux'; - -import { countersReducer, CountersState } from '@src/redux/counters'; -import { todosReducer, TodosState } from '@src/redux/todos'; +import { routerReducer } from 'react-router-redux'; -interface StoreEnhancerState { } - -export interface RootState extends StoreEnhancerState { - router: RouterState; - counters: CountersState; - todos: TodosState; -} +import { countersReducer } from '@src/redux/counters'; +import { todosReducer} from '@src/redux/todos'; import { RootAction } from '@src/redux'; -export const rootReducer = combineReducers({ + +const reducerMap = { router: routerReducer, counters: countersReducer, todos: todosReducer, -}); +}; + +interface StoreEnhancerState { } + +export type RootState = { [K in keyof typeof reducerMap]: ReturnType } & StoreEnhancerState; + +export const rootReducer = combineReducers(reducerMap); ``` diff --git a/docs/markdown/2_redux.md b/docs/markdown/2_redux.md index 0112fcd..91e9d72 100644 --- a/docs/markdown/2_redux.md +++ b/docs/markdown/2_redux.md @@ -93,7 +93,9 @@ state.counterPairs[0].immutableCounter2 = 1; // Error, cannot be mutated ### Create Root State and Root Action Types #### `RootState` - interface representing redux state tree -Can be imported in connected components to provide type-safety to Redux `connect` function +Can be imported in connected components to provide type-safety to Redux `connect` function. + +Because the RootState is the sum of it's reducers' return types (plus any store Enhancers we may choose to append), TypeScript can infer its shape entirely from Lookup Types and `ReturnType<>`. ::example='../../playground/src/redux/root-reducer.ts':: diff --git a/playground/package.json b/playground/package.json index a1b9850..6a3de48 100644 --- a/playground/package.json +++ b/playground/package.json @@ -56,7 +56,7 @@ "ts-jest": "22.0.1", "tslint": "5.8.0", "tslint-react": "3.3.3", - "typescript": "2.7.2", + "typescript": "2.8.3", "webpack": "3.10.0", "webpack-blocks": "1.0.0-rc.2" } diff --git a/playground/src/hoc/with-error-boundary.tsx b/playground/src/hoc/with-error-boundary.tsx index b3b11f1..c113c86 100644 --- a/playground/src/hoc/with-error-boundary.tsx +++ b/playground/src/hoc/with-error-boundary.tsx @@ -36,7 +36,7 @@ export const withErrorBoundary =

( } render() { - const { children, ...remainingProps } = this.props; + const { children, ...remainingProps } = this.props as any; const { error } = this.state; if (error) { diff --git a/playground/src/hoc/with-state.tsx b/playground/src/hoc/with-state.tsx index d891a4b..fef2e38 100644 --- a/playground/src/hoc/with-state.tsx +++ b/playground/src/hoc/with-state.tsx @@ -31,7 +31,7 @@ export const withState =

( } render() { - const { ...remainingProps } = this.props; + const remainingProps = Object.assign({}, this.props); const { count } = this.state; return ( diff --git a/playground/src/redux/root-reducer.ts b/playground/src/redux/root-reducer.ts index 5720aa8..e208aa7 100644 --- a/playground/src/redux/root-reducer.ts +++ b/playground/src/redux/root-reducer.ts @@ -1,20 +1,19 @@ import { combineReducers } from 'redux'; -import { routerReducer, RouterState } from 'react-router-redux'; +import { routerReducer } from 'react-router-redux'; -import { countersReducer, CountersState } from '@src/redux/counters'; -import { todosReducer, TodosState } from '@src/redux/todos'; - -interface StoreEnhancerState { } - -export interface RootState extends StoreEnhancerState { - router: RouterState; - counters: CountersState; - todos: TodosState; -} +import { countersReducer } from '@src/redux/counters'; +import { todosReducer} from '@src/redux/todos'; import { RootAction } from '@src/redux'; -export const rootReducer = combineReducers({ + +const reducerMap = { router: routerReducer, counters: countersReducer, todos: todosReducer, -}); +}; + +interface StoreEnhancerState { } + +export type RootState = { [K in keyof typeof reducerMap]: ReturnType } & StoreEnhancerState; + +export const rootReducer = combineReducers(reducerMap); diff --git a/playground/yarn.lock b/playground/yarn.lock index bc27761..8ac0886 100644 --- a/playground/yarn.lock +++ b/playground/yarn.lock @@ -7211,9 +7211,9 @@ typesafe-actions@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/typesafe-actions/-/typesafe-actions-1.1.2.tgz#af88ede3ee254be425c3e0e02de11b182830ae48" -typescript@2.7.2: - version "2.7.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.7.2.tgz#2d615a1ef4aee4f574425cdff7026edf81919836" +typescript@2.8.3: + version "2.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170" typescript@^2.4.2: version "2.6.2"