react-redux-typescript
Advanced tools
Comparing version 2.1.0 to 2.2.0
{ | ||
"name": "react-redux-typescript", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "React / Redux / TypeScript Utils", | ||
@@ -5,0 +5,0 @@ "author": "Piotr Witek <piotrek.witek@gmail.com> (http://piotrwitek.github.io)", |
122
README.md
# React / Redux / TypeScript Utils | ||
> Redux helpers for Type-safety (action types, action creators, reducers) | ||
- Semantic Versioning | ||
- No external dependencies | ||
- 100% test coverage | ||
- Fully typed Redux (action types, action creators, reducers) | ||
- Futureproof - output es5 and es6 bundles | ||
- output es5 and es6 bundles | ||
### Types | ||
### Table of Contents | ||
- [Helpers v3.0](#helpers-v30) | ||
- [Helpers v2.0](#helpers-v20) | ||
- [returntypeof polyfill](#returntypeof-polyfill) | ||
--- | ||
### Helpers v2.2 | ||
```ts | ||
export class ActionCreator<T, P> { | ||
readonly type: T; | ||
readonly payload: P; | ||
constructor(type: T) { this.type = type; } | ||
create = (payload: P) => ({ type: this.type, payload }); | ||
} | ||
// Example: | ||
import { ActionCreator } from 'react-redux-typescript'; | ||
export const ActionCreators = { | ||
IncreaseCounter: new ActionCreator<'IncreaseCounter', number>('IncreaseCounter'), | ||
ChangeBaseCurrency: new ActionCreator<'ChangeBaseCurrency', string>('ChangeBaseCurrency'), | ||
}; | ||
store.dispatch(ActionCreators.IncreaseCounter.create(4)); // { type: "IncreaseCounter", payload: 4 } | ||
store.dispatch(ActionCreators.ChangeBaseCurrency.create('USD')); // { type: "ChangeBaseCurrency", payload: 'USD' } | ||
// Action Types | ||
type Action = typeof ActionCreators[keyof typeof ActionCreators]; | ||
// { type: "IncreaseCounter", payload: number } | { type: "ChangeBaseCurrency", payload: string } | ||
// Reducer vvvvvv | ||
export default function reducer(state: State = initialState, action: Action): State { | ||
if (action.type === ActionCreators.IncreaseCounter.type) { | ||
state.counter = action.payload; // number | ||
} | ||
else if (action.type === ActionCreators.ChangeBaseCurrency.type) { | ||
state.baseCurrency = action.payload; // string | ||
} | ||
... | ||
``` | ||
--- | ||
### Helpers v2.0 | ||
```ts | ||
/** | ||
* @type EmptyAction - Empty Action Type | ||
* @template T - Type | ||
* @template T - Generic Type | ||
*/ | ||
@@ -20,4 +66,4 @@ export type EmptyAction<T> = { | ||
* @type PayloadAction - Flux Standard Action Type | ||
* @template T - Type | ||
* @template P - Payload | ||
* @template T - Generic Type | ||
* @template P - Generic Type | ||
*/ | ||
@@ -30,38 +76,46 @@ export type PayloadAction<T, P> = { | ||
export function createEmptyAction<T>(type: T): () => EmptyAction<T> { | ||
return () => ({ type }); | ||
}; | ||
export function createPayloadAction<T, P>(type: T): (payload: P) => PayloadAction<T, P> { | ||
return (payload) => ({ type, payload }); | ||
} | ||
``` | ||
### Helper Functions | ||
--- | ||
### returntypeof polyfill | ||
```ts | ||
/** | ||
* @export createEmptyAction - empty action creator function | ||
* @template T - Type | ||
* @param type: T | ||
* @returns () => EmptyAction<T> | ||
*/ | ||
createEmptyAction<T>(type) | ||
// returntypeof() - extract return type of an "expression" | ||
// this polyfill exist because TypeScript does not support this feature yet | ||
// (tracking issue: https://github.com/Microsoft/TypeScript/issues/6606) | ||
export function returntypeof<RT>(expression: (...params: any[]) => RT): RT { | ||
return {} as RT; | ||
} | ||
/** | ||
* @export createPayloadAction - FSA action creator function | ||
* @template T - Type | ||
* @template P - Payload | ||
* @param type: T | ||
* @returns (payload: P) => PayloadAction<T, P> | ||
*/ | ||
createPayloadAction<T, P>(type) | ||
// Example: | ||
import { returntypeof } from 'react-redux-typescript'; | ||
``` | ||
const mapStateToProps = (state: RootState) => ({ | ||
counter: state.counter, | ||
baseCurrency: state.baseCurrency, | ||
currencies: CurrencyRatesSelectors.getCurrencies(state), | ||
}); | ||
### TypeScript Patches | ||
```ts | ||
/** | ||
* @export returntypeof - typeof patch to extract return type of "expression/function" | ||
* Indispensable until native support will arrive in TS | ||
* https://github.com/Microsoft/TypeScript/issues/6606 | ||
* @template RT - ReturnType | ||
* @param expression: (...params: any[]) => RT | ||
* @returns RT | ||
*/ | ||
returntypeof(expression) | ||
const dispatchToProps = { | ||
increaseCounter: ActionCreators.IncreaseCounter.create, | ||
changeBaseCurrency: ActionCreators.ChangeBaseCurrency.create, | ||
}; | ||
export default connect(mapStateToProps, dispatchToProps)(CurrencyConverterContainer); | ||
// Props types inferred from mapStateToProps & dispatchToProps | ||
const stateProps = returntypeof(mapStateToProps); | ||
type Props = typeof stateProps & typeof dispatchToProps; | ||
type State = {}; | ||
class CurrencyConverterContainer extends React.Component<Props, State> { | ||
``` | ||
Copyright (c) 2016 Piotr Witek <piotrek.witek@gmail.com> (http://piotrwitek.github.io) |
14706
120