### **Goals**
- Complete type safety (with [`--strict`](https://www.typescriptlang.org/docs/handbook/compiler-options.html) flag) without losing type information downstream through all the layers of our application (e.g. no type assertions or hacking with `any` type)
- Make type annotations concise by eliminating redundancy in types using advanced TypeScript Language features like **Type Inference** and **Control flow analysis**
- Reduce repetition and complexity of types with TypeScript focused [complementary libraries](#react-redux-typescript-ecosystem)
### **React, Redux, Typescript Ecosystem**
- [typesafe-actions](https://github.com/piotrwitek/typesafe-actions) - Typesafe utilities for "action-creators" in Redux / Flux Architecture
- [utility-types](https://github.com/piotrwitek/utility-types) - Collection of generic types for TypeScript, complementing built-in mapped types and aliases - think lodash for reusable types.
- [react-redux-typescript-scripts](https://github.com/piotrwitek/react-redux-typescript-scripts) - dev-tools configuration files shared between projects based on this guide
### **Examples**
- Todo-App playground: [Codesandbox](https://codesandbox.io/s/github/piotrwitek/typesafe-actions/tree/master/codesandbox)
- React, Redux, TypeScript - RealWorld App: [Github](https://github.com/piotrwitek/react-redux-typescript-realworld-app) | [Demo](https://react-redux-typescript-realworld-app.netlify.com/)
### **Playground Project**
Check out our Playground Project located in the `/playground` folder. It contains all source files of the code examples found in the guide. They are all tested with the most recent version of TypeScript and 3rd party type-definitions (like `@types/react` or `@types/react-redux`) to ensure the examples are up-to-date and not broken with updated definitions (It's based on `create-react-app --typescript`).
> Playground project was created so that you can simply clone the repository locally and immediately play around with all the component patterns found in the guide. It will help you to learn all the examples from this guide in a real project environment without the need to create complicated environment setup by yourself.
## Contributing Guide
You can help make this project better by contributing. If you're planning to contribute please make sure to check our contributing guide: [CONTRIBUTING.md](/CONTRIBUTING.md)
## Funding
You can also help by funding issues.
Issues like bug fixes or feature requests can be very quickly resolved when funded through the IssueHunt platform.
I highly recommend to add a bounty to the issue that you're waiting for to increase priority and attract contributors willing to work on it.
---
🌟 - _New or updated section_
## Table of Contents
- [React Types Cheatsheet](#react-types-cheatsheet)
- [`React.FC` | `React.FunctionComponent`](#reactfcprops--reactfunctioncomponentprops)
- [`React.Component`](#reactcomponentprops-state)
- [`React.ComponentType`](#reactcomponenttypeprops)
- [`React.ComponentProps`](#reactcomponentpropstypeof-xxx)
- [`React.ReactElement` | `JSX.Element`](#reactreactelement--jsxelement)
- [`React.ReactNode`](#reactreactnode)
- [`React.CSSProperties`](#reactcssproperties)
- [`React.XXXHTMLAttributes`](#reactxxxhtmlattributeshtmlxxxelement)
- [`React.ReactEventHandler`](#reactreacteventhandlerhtmlxxxelement)
- [`React.XXXEvent`](#reactxxxeventhtmlxxxelement)
- [React](#react)
- [Function Components - FC](#function-components---fc)
- [- Counter Component](#--counter-component)
- [- Counter Component with default props](#--counter-component-with-default-props)
- [- Spreading attributes in Component](#--spreading-attributes-in-component)
- [Class Components](#class-components)
- [- Class Counter Component](#--class-counter-component)
- [- Class Component with default props](#--class-component-with-default-props)
- [Generic Components](#generic-components)
- [- Generic List Component](#--generic-list-component)
- [Hooks](#hooks)
- [- useState](#--usestate)
- [- useContext](#--usecontext)
- [- useReducer](#--usereducer)
- [Render Props](#render-props)
- [- Name Provider Component](#--name-provider-component)
- [- Mouse Provider Component](#--mouse-provider-component)
- [Higher-Order Components](#higher-order-components)
- [- HOC wrapping a component](#--hoc-wrapping-a-component)
- [- HOC wrapping a component and injecting props](#--hoc-wrapping-a-component-and-injecting-props)
- [- Nested HOC - wrapping a component, injecting props and connecting to redux 🌟](#--nested-hoc---wrapping-a-component-injecting-props-and-connecting-to-redux-)
- [Redux Connected Components](#redux-connected-components)
- [- Redux connected counter](#--redux-connected-counter)
- [- Redux connected counter with own props](#--redux-connected-counter-with-own-props)
- [- Redux connected counter via hooks](#--redux-connected-counter-via-hooks)
- [- Redux connected counter with `redux-thunk` integration](#--redux-connected-counter-with-redux-thunk-integration)
- [Context](#context)
- [ThemeContext](#themecontext)
- [ThemeProvider](#themeprovider)
- [ThemeConsumer](#themeconsumer)
- [ThemeConsumer in class component](#themeconsumer-in-class-component)
- [Redux](#redux)
- [Store Configuration](#store-configuration)
- [Create Global Store Types](#create-global-store-types)
- [Create Store](#create-store)
- [Action Creators 🌟](#action-creators-)
- [Reducers](#reducers)
- [State with Type-level Immutability](#state-with-type-level-immutability)
- [Typing reducer](#typing-reducer)
- [Typing reducer with `typesafe-actions`](#typing-reducer-with-typesafe-actions)
- [Testing reducer](#testing-reducer)
- [Async Flow with `redux-observable`](#async-flow-with-redux-observable)
- [Typing epics](#typing-epics)
- [Testing epics](#testing-epics)
- [Selectors with `reselect`](#selectors-with-reselect)
- [Connect with `react-redux`](#connect-with-react-redux)
- [Typing connected component](#typing-connected-component)
- [Typing `useSelector` and `useDispatch`](#typing-useselector-and-usedispatch)
- [Typing connected component with `redux-thunk` integration](#typing-connected-component-with-redux-thunk-integration)
- [Configuration & Dev Tools](#configuration--dev-tools)
- [Common Npm Scripts](#common-npm-scripts)
- [tsconfig.json](#tsconfigjson)
- [TSLib](#tslib)
- [ESLint](#eslint)
- [.eslintrc.js](#eslintrcjs)
- [Jest](#jest)
- [jest.config.json](#jestconfigjson)
- [jest.stubs.js](#jeststubsjs)
- [Style Guides](#style-guides)
- [react-styleguidist](#react-styleguidist)
- [FAQ](#faq)
- [Ambient Modules](#ambient-modules)
- [Imports in ambient modules](#imports-in-ambient-modules)
- [Type-Definitions](#type-definitions)
- [Missing type-definitions error](#missing-type-definitions-error)
- [Using custom `d.ts` files for npm modules](#using-custom-dts-files-for-npm-modules)
- [Type Augmentation](#type-augmentation)
- [Augmenting library internal declarations - using relative import](#augmenting-library-internal-declarations---using-relative-import)
- [Augmenting library public declarations - using node_modules import](#augmenting-library-public-declarations---using-node_modules-import)
- [Misc](#misc)
- [- should I still use React.PropTypes in TS?](#--should-i-still-use-reactproptypes-in-ts)
- [- when to use `interface` declarations and when `type` aliases?](#--when-to-use-interface-declarations-and-when-type-aliases)
- [- what's better default or named exports?](#--whats-better-default-or-named-exports)
- [- how to best initialize class instance or static properties?](#--how-to-best-initialize-class-instance-or-static-properties)
- [- how to best declare component handler functions?](#--how-to-best-declare-component-handler-functions)
- [Tutorials & Articles](#tutorials--articles)
- [Contributors](#contributors)
---
# Installation
## Types for React & Redux
```
npm i -D @types/react @types/react-dom @types/react-redux
```
"react" - `@types/react`
"react-dom" - `@types/react-dom`
"redux" - (types included with npm package)*
"react-redux" - `@types/react-redux`
> *NB: Guide is based on types for Redux >= v4.x.x.
[⇧ back to top](#table-of-contents)
---
## React Types Cheatsheet
### `React.FC` | `React.FunctionComponent`
Type representing a functional component
```tsx
const MyComponent: React.FC = ...
```
### `React.Component`
Type representing a class component
```tsx
class MyComponent extends React.Component { ...
```
### `React.ComponentType`
Type representing union of (`React.FC | React.Component`) - used in HOC
```tsx
const withState =
(
WrappedComponent: React.ComponentType
,
) => { ...
```
### `React.ComponentProps`
Gets Props type of a specified component XXX (WARNING: does not work with statically declared default props and generic props)
```tsx
type MyComponentProps = React.ComponentProps;
```
### `React.ReactElement` | `JSX.Element`
Type representing a concept of React Element - representation of a native DOM component (e.g. `
);
};
```
[⟩⟩⟩ demo](https://piotrwitek.github.io/react-redux-typescript-guide/#fccounter)
[⇧ back to top](#table-of-contents)
### - Counter Component with default props
```tsx
import * as React from 'react';
type Props = {
label: string;
count: number;
onIncrement: () => void;
};
// React.FC is unaplicable here due not working properly with default props
// https://github.com/facebook/create-react-app/pull/8177
export const FCCounterWithDefaultProps = (props: Props): JSX.Element => {
const { label, count, onIncrement } = props;
const handleIncrement = () => {
onIncrement();
};
return (
);
};
FCCounterWithDefaultProps.defaultProps = { count: 5 };
```
[⟩⟩⟩ demo](https://piotrwitek.github.io/react-redux-typescript-guide/#fccounterwithdefaultprops)
[⇧ back to top](#table-of-contents)
### - [Spreading attributes](https://facebook.github.io/react/docs/jsx-in-depth.html#spread-attributes) in Component
```tsx
import * as React from 'react';
type Props = React.PropsWithChildren<{
className?: string;
style?: React.CSSProperties;
}>;
export const FCSpreadAttributes: React.FC = (props) => {
const { children, ...restProps } = props;
return
;
};
```
[⟩⟩⟩ demo](https://piotrwitek.github.io/react-redux-typescript-guide/#fcspreadattributes)
[⇧ back to top](#table-of-contents)
---
## Class Components
### - Class Counter Component
```tsx
import * as React from 'react';
type Props = {
label: string;
};
type State = {
count: number;
};
export class ClassCounter extends React.Component {
readonly state: State = {
count: 0,
};
handleIncrement = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
const { handleIncrement } = this;
const { label } = this.props;
const { count } = this.state;
return (
);
}
}
```
[⟩⟩⟩ demo](https://piotrwitek.github.io/react-redux-typescript-guide/#classcounter)
[⇧ back to top](#table-of-contents)
### - Class Component with default props
```tsx
import * as React from 'react';
type Props = {
label: string;
initialCount: number;
};
type State = {
count: number;
};
export class ClassCounterWithDefaultProps extends React.Component<
Props,
State
> {
static defaultProps = {
initialCount: 0,
};
readonly state: State = {
count: this.props.initialCount,
};
handleIncrement = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
const { handle