[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-10113":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":19,"rankGlobal":10,"rankLanguage":10,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":23,"topics":24,"createdAt":10,"pushedAt":10,"updatedAt":34,"readmeContent":35,"aiSummary":36,"trendingCount":16,"starSnapshotCount":16,"syncStatus":37,"lastSyncTime":38,"discoverSource":39},10113,"react-redux-typescript-guide","piotrwitek\u002Freact-redux-typescript-guide","piotrwitek","The complete guide to static typing in \"React & Redux\" apps using TypeScript","https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F",null,"TypeScript",13293,1102,184,30,0,1,4,44.13,"MIT License",false,"master",true,[25,26,27,28,29,30,31,32,33],"flow","guide","guidelines","patterns","react","redux","static-typing","style-guide","typescript","2026-06-12 02:02:17","\u003Cdiv align=\"center\">\n\n# React & Redux in TypeScript - Complete Guide\n\n_\"This guide is a **living compendium** documenting the most important patterns and recipes on how to use **React** (and its Ecosystem) in a **functional style** using **TypeScript**. It will help you make your code **completely type-safe** while focusing on **inferring the types from implementation** so there is less noise coming from excessive type annotations and it's easier to write and maintain correct types in the long run.\"_\n\n[![Join the community on Spectrum](https:\u002F\u002Fwithspectrum.github.io\u002Fbadge\u002Fbadge.svg)](https:\u002F\u002Fspectrum.chat\u002Freact-redux-ts)\n[![Join the chat at https:\u002F\u002Fgitter.im\u002Freact-redux-typescript-guide\u002FLobby](https:\u002F\u002Fbadges.gitter.im\u002FJoin%20Chat.svg)](https:\u002F\u002Fgitter.im\u002Freact-redux-typescript-guide\u002FLobby)\n\n_Found it useful? Want more updates?_\n\n[**Show your support by giving a :star:**](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fstargazers)\n\n\u003Ca href=\"https:\u002F\u002Fwww.buymeacoffee.com\u002Fpiotrekwitek\">\n  \u003Cimg src=\"https:\u002F\u002Fwww.buymeacoffee.com\u002Fassets\u002Fimg\u002Fcustom_images\u002Forange_img.png\" alt=\"Buy Me a Coffee\">\n\u003C\u002Fa>\n\u003Ca href=\"https:\u002F\u002Fwww.patreon.com\u002Fpiotrekwitek\">\n  \u003Cimg src=\"https:\u002F\u002Fc5.patreon.com\u002Fexternal\u002Flogo\u002Fbecome_a_patron_button@2x.png\" alt=\"Become a Patron\" width=\"160\">\n\u003C\u002Fa>\n\n\u003Cbr\u002F>\u003Chr\u002F>\n\n## **What's new?**\n\n:tada: _Now updated to support **TypeScript v4.6**_ :tada:\n:rocket: _Updated to `typesafe-actions@5.x` :rocket:\n\n\u003Chr\u002F>\u003Cbr\u002F>\n\n\u003C\u002Fdiv>\n\n### **Goals**\n\n- Complete type safety (with [`--strict`](https:\u002F\u002Fwww.typescriptlang.org\u002Fdocs\u002Fhandbook\u002Fcompiler-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)\n- Make type annotations concise by eliminating redundancy in types using advanced TypeScript Language features like **Type Inference** and **Control flow analysis**\n- Reduce repetition and complexity of types with TypeScript focused [complementary libraries](#react-redux-typescript-ecosystem)\n\n### **React, Redux, Typescript Ecosystem**\n\n- [typesafe-actions](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Ftypesafe-actions) - Typesafe utilities for \"action-creators\" in Redux \u002F Flux Architecture  \n- [utility-types](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Futility-types) - Collection of generic types for TypeScript, complementing built-in mapped types and aliases - think lodash for reusable types.  \n- [react-redux-typescript-scripts](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-scripts) - dev-tools configuration files shared between projects based on this guide  \n\n### **Examples**\n\n- Todo-App playground: [Codesandbox](https:\u002F\u002Fcodesandbox.io\u002Fs\u002Fgithub\u002Fpiotrwitek\u002Ftypesafe-actions\u002Ftree\u002Fmaster\u002Fcodesandbox)\n- React, Redux, TypeScript - RealWorld App: [Github](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-realworld-app) | [Demo](https:\u002F\u002Freact-redux-typescript-realworld-app.netlify.com\u002F)\n\n### **Playground Project**\n\n[![Build Status](https:\u002F\u002Fsemaphoreci.com\u002Fapi\u002Fv1\u002Fpiotrekwitek\u002Freact-redux-typescript-guide\u002Fbranches\u002Fmaster\u002Fshields_badge.svg)](https:\u002F\u002Fsemaphoreci.com\u002Fpiotrekwitek\u002Freact-redux-typescript-guide)\n\nCheck out our Playground Project located in the `\u002Fplayground` 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\u002Freact` or `@types\u002Freact-redux`) to ensure the examples are up-to-date and not broken with updated definitions (It's based on `create-react-app --typescript`).\n> 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.\n\n## Contributing Guide\n\nYou can help make this project better by contributing. If you're planning to contribute please make sure to check our contributing guide: [CONTRIBUTING.md](\u002FCONTRIBUTING.md)\n\n## Funding\n\nYou can also help by funding issues.\nIssues like bug fixes or feature requests can be very quickly resolved when funded through the IssueHunt platform.\n\nI 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.\n\n[![Let's fund issues in this repository](https:\u002F\u002Fissuehunt.io\u002Fstatic\u002Fembed\u002Fissuehunt-button-v1.svg)](https:\u002F\u002Fissuehunt.io\u002Frepos\u002F76996763)\n\n---\n\n🌟 - _New or updated section_\n\n## Table of Contents\n\n\u003C!-- START doctoc generated TOC please keep comment here to allow auto update -->\n\u003C!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n\n\n  - [React Types Cheatsheet](#react-types-cheatsheet)\n    - [`React.FC\u003CProps>` | `React.FunctionComponent\u003CProps>`](#reactfcprops--reactfunctioncomponentprops)\n    - [`React.Component\u003CProps, State>`](#reactcomponentprops-state)\n    - [`React.ComponentType\u003CProps>`](#reactcomponenttypeprops)\n    - [`React.ComponentProps\u003Ctypeof XXX>`](#reactcomponentpropstypeof-xxx)\n    - [`React.ReactElement` | `JSX.Element`](#reactreactelement--jsxelement)\n    - [`React.ReactNode`](#reactreactnode)\n    - [`React.CSSProperties`](#reactcssproperties)\n    - [`React.XXXHTMLAttributes\u003CHTMLXXXElement>`](#reactxxxhtmlattributeshtmlxxxelement)\n    - [`React.ReactEventHandler\u003CHTMLXXXElement>`](#reactreacteventhandlerhtmlxxxelement)\n    - [`React.XXXEvent\u003CHTMLXXXElement>`](#reactxxxeventhtmlxxxelement)\n- [React](#react)\n  - [Function Components - FC](#function-components---fc)\n    - [- Counter Component](#--counter-component)\n    - [- Counter Component with default props](#--counter-component-with-default-props)\n    - [- Spreading attributes in Component](#--spreading-attributes-in-component)\n  - [Class Components](#class-components)\n    - [- Class Counter Component](#--class-counter-component)\n    - [- Class Component with default props](#--class-component-with-default-props)\n  - [Generic Components](#generic-components)\n    - [- Generic List Component](#--generic-list-component)\n  - [Hooks](#hooks)\n    - [- useState](#--usestate)\n    - [- useContext](#--usecontext)\n    - [- useReducer](#--usereducer)\n  - [Render Props](#render-props)\n    - [- Name Provider Component](#--name-provider-component)\n    - [- Mouse Provider Component](#--mouse-provider-component)\n  - [Higher-Order Components](#higher-order-components)\n    - [- HOC wrapping a component](#--hoc-wrapping-a-component)\n    - [- HOC wrapping a component and injecting props](#--hoc-wrapping-a-component-and-injecting-props)\n    - [- Nested HOC - wrapping a component, injecting props and connecting to redux 🌟](#--nested-hoc---wrapping-a-component-injecting-props-and-connecting-to-redux-)\n  - [Redux Connected Components](#redux-connected-components)\n    - [- Redux connected counter](#--redux-connected-counter)\n    - [- Redux connected counter with own props](#--redux-connected-counter-with-own-props)\n    - [- Redux connected counter via hooks](#--redux-connected-counter-via-hooks)\n    - [- Redux connected counter with `redux-thunk` integration](#--redux-connected-counter-with-redux-thunk-integration)\n  - [Context](#context)\n    - [ThemeContext](#themecontext)\n    - [ThemeProvider](#themeprovider)\n    - [ThemeConsumer](#themeconsumer)\n    - [ThemeConsumer in class component](#themeconsumer-in-class-component)\n- [Redux](#redux)\n  - [Store Configuration](#store-configuration)\n    - [Create Global Store Types](#create-global-store-types)\n    - [Create Store](#create-store)\n  - [Action Creators 🌟](#action-creators-)\n  - [Reducers](#reducers)\n    - [State with Type-level Immutability](#state-with-type-level-immutability)\n    - [Typing reducer](#typing-reducer)\n    - [Typing reducer with `typesafe-actions`](#typing-reducer-with-typesafe-actions)\n    - [Testing reducer](#testing-reducer)\n  - [Async Flow with `redux-observable`](#async-flow-with-redux-observable)\n    - [Typing epics](#typing-epics)\n    - [Testing epics](#testing-epics)\n  - [Selectors with `reselect`](#selectors-with-reselect)\n  - [Connect with `react-redux`](#connect-with-react-redux)\n    - [Typing connected component](#typing-connected-component)\n    - [Typing `useSelector` and `useDispatch`](#typing-useselector-and-usedispatch)\n    - [Typing connected component with `redux-thunk` integration](#typing-connected-component-with-redux-thunk-integration)\n- [Configuration & Dev Tools](#configuration--dev-tools)\n  - [Common Npm Scripts](#common-npm-scripts)\n  - [tsconfig.json](#tsconfigjson)\n  - [TSLib](#tslib)\n  - [ESLint](#eslint)\n    - [.eslintrc.js](#eslintrcjs)\n  - [Jest](#jest)\n    - [jest.config.json](#jestconfigjson)\n    - [jest.stubs.js](#jeststubsjs)\n  - [Style Guides](#style-guides)\n    - [react-styleguidist](#react-styleguidist)\n- [FAQ](#faq)\n  - [Ambient Modules](#ambient-modules)\n    - [Imports in ambient modules](#imports-in-ambient-modules)\n  - [Type-Definitions](#type-definitions)\n    - [Missing type-definitions error](#missing-type-definitions-error)\n    - [Using custom `d.ts` files for npm modules](#using-custom-dts-files-for-npm-modules)\n  - [Type Augmentation](#type-augmentation)\n    - [Augmenting library internal declarations - using relative import](#augmenting-library-internal-declarations---using-relative-import)\n    - [Augmenting library public declarations - using node_modules import](#augmenting-library-public-declarations---using-node_modules-import)\n  - [Misc](#misc)\n    - [- should I still use React.PropTypes in TS?](#--should-i-still-use-reactproptypes-in-ts)\n    - [- when to use `interface` declarations and when `type` aliases?](#--when-to-use-interface-declarations-and-when-type-aliases)\n    - [- what's better default or named exports?](#--whats-better-default-or-named-exports)\n    - [- how to best initialize class instance or static properties?](#--how-to-best-initialize-class-instance-or-static-properties)\n    - [- how to best declare component handler functions?](#--how-to-best-declare-component-handler-functions)\n- [Tutorials & Articles](#tutorials--articles)\n- [Contributors](#contributors)\n\n\u003C!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n---\n\n# Installation\n\n## Types for React & Redux\n\n```\nnpm i -D @types\u002Freact @types\u002Freact-dom @types\u002Freact-redux\n```\n\n\"react\" - `@types\u002Freact`  \n\"react-dom\" - `@types\u002Freact-dom`  \n\"redux\" - (types included with npm package)*  \n\"react-redux\" - `@types\u002Freact-redux`  \n\n> *NB: Guide is based on types for Redux >= v4.x.x.\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## React Types Cheatsheet\n\n### `React.FC\u003CProps>` | `React.FunctionComponent\u003CProps>`\n\nType representing a functional component\n\n```tsx\nconst MyComponent: React.FC\u003CProps> = ...\n```\n\n### `React.Component\u003CProps, State>`\n\nType representing a class component\n\n```tsx\nclass MyComponent extends React.Component\u003CProps, State> { ...\n```\n\n### `React.ComponentType\u003CProps>`\n\nType representing union of (`React.FC\u003CProps> | React.Component\u003CProps>`) - used in HOC\n\n```tsx\nconst withState = \u003CP extends WrappedComponentProps>(\n  WrappedComponent: React.ComponentType\u003CP>,\n) => { ...\n```\n\n### `React.ComponentProps\u003Ctypeof XXX>`\n\nGets Props type of a specified component XXX (WARNING: does not work with statically declared default props and generic props)\n\n```tsx\ntype MyComponentProps = React.ComponentProps\u003Ctypeof MyComponent>;\n```\n\n### `React.ReactElement` | `JSX.Element`\n\nType representing a concept of React Element - representation of a native DOM component (e.g. `\u003Cdiv \u002F>`), or a user-defined composite component (e.g. `\u003CMyComponent \u002F>`)\n\n```tsx\nconst elementOnly: React.ReactElement = \u003Cdiv \u002F> || \u003CMyComponent \u002F>;\n```\n\n### `React.ReactNode`\n\nType representing any possible type of React node (basically ReactElement (including Fragments and Portals) + primitive JS types)\n\n```tsx\nconst elementOrPrimitive: React.ReactNode = 'string' || 0 || false || null || undefined || \u003Cdiv \u002F> || \u003CMyComponent \u002F>;\nconst Component = ({ children: React.ReactNode }) => ...\n```\n\n### `React.CSSProperties`\n\nType representing style object in JSX - for css-in-js styles\n\n```tsx\nconst styles: React.CSSProperties = { flexDirection: 'row', ...\nconst element = \u003Cdiv style={styles} ...\n```\n\n### `React.XXXHTMLAttributes\u003CHTMLXXXElement>`\n\nType representing HTML attributes of specified HTML Element - for extending HTML Elements\n\n```tsx\nconst Input: React.FC\u003CProps & React.InputHTMLAttributes\u003CHTMLInputElement>> = props => { ... }\n\n\u003CInput about={...} accept={...} alt={...} ... \u002F>\n```\n\n### `React.ReactEventHandler\u003CHTMLXXXElement>`\n\nType representing generic event handler - for declaring event handlers\n\n```tsx\nconst handleChange: React.ReactEventHandler\u003CHTMLInputElement> = (ev) => { ... } \n\n\u003Cinput onChange={handleChange} ... \u002F>\n```\n\n### `React.XXXEvent\u003CHTMLXXXElement>`\n\nType representing more specific event. Some common event examples: `ChangeEvent, FormEvent, FocusEvent, KeyboardEvent, MouseEvent, DragEvent, PointerEvent, WheelEvent, TouchEvent`.\n\n```tsx\nconst handleChange = (ev: React.MouseEvent\u003CHTMLDivElement>) => { ... }\n\n\u003Cdiv onMouseMove={handleChange} ... \u002F>\n```\n\nIn code above `React.MouseEvent\u003CHTMLDivElement>` is type of mouse event, and this event happened on `HTMLDivElement`\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n# React\n\n## Function Components - FC\n\n### - Counter Component\n\n```tsx\nimport * as React from 'react';\n\ntype Props = {\n  label: string;\n  count: number;\n  onIncrement: () => void;\n};\n\nexport const FCCounter: React.FC\u003CProps> = props => {\n  const { label, count, onIncrement } = props;\n\n  const handleIncrement = () => {\n    onIncrement();\n  };\n\n  return (\n    \u003Cdiv>\n      \u003Cspan>\n        {label}: {count}\n      \u003C\u002Fspan>\n      \u003Cbutton type=\"button\" onClick={handleIncrement}>\n        {`Increment`}\n      \u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  );\n};\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#fccounter)\n\n[⇧ back to top](#table-of-contents)\n\n### - Counter Component with default props\n\n```tsx\nimport * as React from 'react';\n\ntype Props = {\n  label: string;\n  count: number;\n  onIncrement: () => void;\n};\n\n\u002F\u002F React.FC is unaplicable here due not working properly with default props\n\u002F\u002F https:\u002F\u002Fgithub.com\u002Ffacebook\u002Fcreate-react-app\u002Fpull\u002F8177\nexport const FCCounterWithDefaultProps = (props: Props): JSX.Element => {\n  const { label, count, onIncrement } = props;\n\n  const handleIncrement = () => {\n    onIncrement();\n  };\n\n  return (\n    \u003Cdiv>\n      \u003Cspan>\n        {label}: {count}\n      \u003C\u002Fspan>\n      \u003Cbutton type=\"button\" onClick={handleIncrement}>\n        {`Increment`}\n      \u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  );\n};\n\nFCCounterWithDefaultProps.defaultProps = { count: 5 };\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#fccounterwithdefaultprops)\n\n[⇧ back to top](#table-of-contents)\n\n### - [Spreading attributes](https:\u002F\u002Ffacebook.github.io\u002Freact\u002Fdocs\u002Fjsx-in-depth.html#spread-attributes) in Component\n\n```tsx\nimport * as React from 'react';\n\ntype Props = React.PropsWithChildren\u003C{\n  className?: string;\n  style?: React.CSSProperties;\n}>;\n\nexport const FCSpreadAttributes: React.FC\u003CProps> = (props) => {\n  const { children, ...restProps } = props;\n\n  return \u003Cdiv {...restProps}>{children}\u003C\u002Fdiv>;\n};\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#fcspreadattributes)\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Class Components\n\n### - Class Counter Component\n\n```tsx\nimport * as React from 'react';\n\ntype Props = {\n  label: string;\n};\n\ntype State = {\n  count: number;\n};\n\nexport class ClassCounter extends React.Component\u003CProps, State> {\n  readonly state: State = {\n    count: 0,\n  };\n\n  handleIncrement = () => {\n    this.setState({ count: this.state.count + 1 });\n  };\n\n  render() {\n    const { handleIncrement } = this;\n    const { label } = this.props;\n    const { count } = this.state;\n\n    return (\n      \u003Cdiv>\n        \u003Cspan>\n          {label}: {count}\n        \u003C\u002Fspan>\n        \u003Cbutton type=\"button\" onClick={handleIncrement}>\n          {`Increment`}\n        \u003C\u002Fbutton>\n      \u003C\u002Fdiv>\n    );\n  }\n}\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#classcounter)\n\n[⇧ back to top](#table-of-contents)\n\n### - Class Component with default props\n\n```tsx\nimport * as React from 'react';\n\ntype Props = {\n  label: string;\n  initialCount: number;\n};\n\ntype State = {\n  count: number;\n};\n\nexport class ClassCounterWithDefaultProps extends React.Component\u003C\n  Props,\n  State\n> {\n  static defaultProps = {\n    initialCount: 0,\n  };\n\n  readonly state: State = {\n    count: this.props.initialCount,\n  };\n\n  handleIncrement = () => {\n    this.setState({ count: this.state.count + 1 });\n  };\n\n  render() {\n    const { handleIncrement } = this;\n    const { label } = this.props;\n    const { count } = this.state;\n\n    return (\n      \u003Cdiv>\n        \u003Cspan>\n          {label}: {count}\n        \u003C\u002Fspan>\n        \u003Cbutton type=\"button\" onClick={handleIncrement}>\n          {`Increment`}\n        \u003C\u002Fbutton>\n      \u003C\u002Fdiv>\n    );\n  }\n}\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#classcounterwithdefaultprops)\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Generic Components\n\n- easily create typed component variations and reuse common logic\n- common use case is a generic list components\n\n### - Generic List Component\n\n```tsx\nimport * as React from 'react';\n\nexport interface GenericListProps\u003CT> {\n  items: T[];\n  itemRenderer: (item: T) => JSX.Element;\n}\n\nexport class GenericList\u003CT> extends React.Component\u003CGenericListProps\u003CT>, {}> {\n  render() {\n    const { items, itemRenderer } = this.props;\n\n    return (\n      \u003Cdiv>\n        {items.map(itemRenderer)}\n      \u003C\u002Fdiv>\n    );\n  }\n}\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#genericlist)\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Hooks\n\n> \u003Chttps:\u002F\u002Freactjs.org\u002Fdocs\u002Fhooks-intro.html>\n\n### - useState\n\n> \u003Chttps:\u002F\u002Freactjs.org\u002Fdocs\u002Fhooks-reference.html#usestate>\n\n```tsx\nimport * as React from 'react';\n\ntype Props = { initialCount: number };\n\nexport default function Counter({initialCount}: Props) {\n  const [count, setCount] = React.useState(initialCount);\n  return (\n    \u003C>\n      Count: {count}\n      \u003Cbutton onClick={() => setCount(initialCount)}>Reset\u003C\u002Fbutton>\n      \u003Cbutton onClick={() => setCount(prevCount => prevCount + 1)}>+\u003C\u002Fbutton>\n      \u003Cbutton onClick={() => setCount(prevCount => prevCount - 1)}>-\u003C\u002Fbutton>\n    \u003C\u002F>\n  );\n}\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### - useContext\n\n> \u003Chttps:\u002F\u002Freactjs.org\u002Fdocs\u002Fhooks-reference.html#usecontext>\n\n```tsx\nimport * as React from 'react';\nimport ThemeContext from '..\u002Fcontext\u002Ftheme-context';\n\ntype Props = {};\n\nexport default function ThemeToggleButton(props: Props) {\n  const { theme, toggleTheme } = React.useContext(ThemeContext);\n  return (\n    \u003Cbutton onClick={toggleTheme} style={theme} >\n      Toggle Theme\n    \u003C\u002Fbutton>\n  );\n}\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### - useReducer\n\n> \u003Chttps:\u002F\u002Freactjs.org\u002Fdocs\u002Fhooks-reference.html#usereducer>\n\n```tsx\nimport * as React from 'react';\n\ninterface State {\n  count: number;\n}\n\ntype Action = { type: 'reset' } | { type: 'increment' } | { type: 'decrement' };\n\nfunction reducer(state: State, action: Action): State {\n  switch (action.type) {\n    case 'increment':\n      return { count: state.count + 1 };\n    case 'decrement':\n      return { count: state.count - 1 };\n    case 'reset':\n      return { count: 0 };\n    default:\n      throw new Error();\n  }\n}\n\ninterface CounterProps {\n  initialCount: number;\n}\n\nfunction Counter({ initialCount }: CounterProps) {\n  const [state, dispatch] = React.useReducer(reducer, {\n    count: initialCount,\n  });\n\n  return (\n    \u003C>\n      Count: {state.count}\n      \u003Cbutton onClick={() => dispatch({ type: 'reset' })}>Reset\u003C\u002Fbutton>\n      \u003Cbutton onClick={() => dispatch({ type: 'increment' })}>+\u003C\u002Fbutton>\n      \u003Cbutton onClick={() => dispatch({ type: 'decrement' })}>-\u003C\u002Fbutton>\n    \u003C\u002F>\n  );\n}\n\nexport default Counter;\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Render Props\n\n> \u003Chttps:\u002F\u002Freactjs.org\u002Fdocs\u002Frender-props.html>\n\n### - Name Provider Component\n\nSimple component using children as a render prop\n\n```tsx\nimport * as React from 'react';\n\ninterface NameProviderProps {\n  children: (state: NameProviderState) => React.ReactNode;\n}\n\ninterface NameProviderState {\n  readonly name: string;\n}\n\nexport class NameProvider extends React.Component\u003CNameProviderProps, NameProviderState> {\n  readonly state: NameProviderState = { name: 'Piotr' };\n\n  render() {\n    return this.props.children(this.state);\n  }\n}\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#nameprovider)\n\n[⇧ back to top](#table-of-contents)\n\n### - Mouse Provider Component\n\n`Mouse` component found in [Render Props React Docs](https:\u002F\u002Freactjs.org\u002Fdocs\u002Frender-props.html#use-render-props-for-cross-cutting-concerns)\n\n```tsx\nimport * as React from 'react';\n\nexport interface MouseProviderProps {\n  render: (state: MouseProviderState) => React.ReactNode;\n}\n\ninterface MouseProviderState {\n  readonly x: number;\n  readonly y: number;\n}\n\nexport class MouseProvider extends React.Component\u003CMouseProviderProps, MouseProviderState> {\n  readonly state: MouseProviderState = { x: 0, y: 0 };\n\n  handleMouseMove = (event: React.MouseEvent\u003CHTMLDivElement>) => {\n    this.setState({\n      x: event.clientX,\n      y: event.clientY,\n    });\n  };\n\n  render() {\n    return (\n      \u003Cdiv style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>\n        {\u002F*\n          Instead of providing a static representation of what \u003CMouse> renders,\n          use the `render` prop to dynamically determine what to render.\n        *\u002F}\n        {this.props.render(this.state)}\n      \u003C\u002Fdiv>\n    );\n  }\n}\n\n```\n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F#mouseprovider)\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Higher-Order Components\n\n> \u003Chttps:\u002F\u002Freactjs.org\u002Fdocs\u002Fhigher-order-components.html>\n\n### - HOC wrapping a component\n\nAdds state to a stateless counter\n\n```tsx\nimport React from 'react';\nimport { Diff } from 'utility-types';\n\n\u002F\u002F These props will be injected into the base component\ninterface InjectedProps {\n  count: number;\n  onIncrement: () => void;\n}\n\nexport const withState = \u003CBaseProps extends InjectedProps>(\n  BaseComponent: React.ComponentType\u003CBaseProps>\n) => {\n  type HocProps = Diff\u003CBaseProps, InjectedProps> & {\n    \u002F\u002F here you can extend hoc with new props\n    initialCount?: number;\n  };\n  type HocState = {\n    readonly count: number;\n  };\n\n  return class Hoc extends React.Component\u003CHocProps, HocState> {\n    \u002F\u002F Enhance component name for debugging and React-Dev-Tools\n    static displayName = `withState(${BaseComponent.name})`;\n    \u002F\u002F reference to original wrapped component\n    static readonly WrappedComponent = BaseComponent;\n\n    readonly state: HocState = {\n      count: Number(this.props.initialCount) || 0,\n    };\n\n    handleIncrement = () => {\n      this.setState({ count: this.state.count + 1 });\n    };\n\n    render() {\n      const { ...restProps } = this.props;\n      const { count } = this.state;\n\n      return (\n        \u003CBaseComponent\n        {...(restProps as BaseProps)}\n          count={count} \u002F\u002F injected\n          onIncrement={this.handleIncrement} \u002F\u002F injected\n        \u002F>\n      );\n    }\n  };\n};\n\n```\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nimport * as React from 'react';\n\nimport { withState } from '..\u002Fhoc';\nimport { FCCounter } from '..\u002Fcomponents';\n\nconst FCCounterWithState = withState(FCCounter);\n\nexport default () => \u003CFCCounterWithState label={'FCCounterWithState'} \u002F>;\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n### - HOC wrapping a component and injecting props\n\nAdds error handling using componentDidCatch to any component\n\n```tsx\nimport React from 'react';\n\nconst MISSING_ERROR = 'Error was swallowed during propagation.';\n\nexport const withErrorBoundary = \u003CBaseProps extends {}>(\n  BaseComponent: React.ComponentType\u003CBaseProps>\n) => {\n  type HocProps = React.PropsWithChildren\u003C{\n    \u002F\u002F here you can extend hoc with new props\n  }>;\n  type HocState = {\n    readonly error: Error | null | undefined;\n  };\n\n  return class Hoc extends React.Component\u003CHocProps, HocState> {\n    \u002F\u002F Enhance component name for debugging and React-Dev-Tools\n    static displayName = `withErrorBoundary(${BaseComponent.name})`;\n    \u002F\u002F reference to original wrapped component\n    static readonly WrappedComponent = BaseComponent;\n\n    readonly state: HocState = {\n      error: undefined,\n    };\n\n    componentDidCatch(error: Error | null, info: object) {\n      this.setState({ error: error || new Error(MISSING_ERROR) });\n      this.logErrorToCloud(error, info);\n    }\n\n    logErrorToCloud = (error: Error | null, info: object) => {\n      \u002F\u002F TODO: send error report to service provider\n    };\n\n    render() {\n      const { children, ...restProps } = this.props;\n      const { error } = this.state;\n\n      if (error) {\n        return \u003CBaseComponent {...(restProps as BaseProps)} \u002F>;\n      }\n\n      return children;\n    }\n  };\n};\n\n```\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nimport React, {useState} from 'react';\n\nimport { withErrorBoundary } from '..\u002Fhoc';\nimport { ErrorMessage } from '..\u002Fcomponents';\n\nconst ErrorMessageWithErrorBoundary =\n  withErrorBoundary(ErrorMessage);\n\nconst BrokenComponent = () => {\n  throw new Error('I\\'m broken! Don\\'t render me.');\n};\n\nconst BrokenButton = () => {\n  const [shouldRenderBrokenComponent, setShouldRenderBrokenComponent] =\n    useState(false);\n\n  if (shouldRenderBrokenComponent) {\n    return \u003CBrokenComponent \u002F>;\n  }\n\n  return (\n    \u003Cbutton\n      type=\"button\"\n      onClick={() => {\n        setShouldRenderBrokenComponent(true);\n      }}\n    >\n      {`Throw nasty error`}\n    \u003C\u002Fbutton>\n  );\n};\n\nexport default () => (\n  \u003CErrorMessageWithErrorBoundary>\n    \u003CBrokenButton \u002F>\n  \u003C\u002FErrorMessageWithErrorBoundary>\n);\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n### - Nested HOC - wrapping a component, injecting props and connecting to redux 🌟\n\nAdds error handling using componentDidCatch to any component\n\n```tsx\nimport { RootState } from 'MyTypes';\nimport React from 'react';\nimport { connect } from 'react-redux';\nimport { Diff } from 'utility-types';\nimport { countersActions, countersSelectors } from '..\u002Ffeatures\u002Fcounters';\n\n\u002F\u002F These props will be injected into the base component\ninterface InjectedProps {\n  count: number;\n  onIncrement: () => void;\n}\n\nexport const withConnectedCount = \u003CBaseProps extends InjectedProps>(\n  BaseComponent: React.ComponentType\u003CBaseProps>\n) => {\n  const mapStateToProps = (state: RootState) => ({\n    count: countersSelectors.getReduxCounter(state.counters),\n  });\n\n  const dispatchProps = {\n    onIncrement: countersActions.increment,\n  };\n\n  type HocProps = ReturnType\u003Ctypeof mapStateToProps> &\n    typeof dispatchProps & {\n      \u002F\u002F here you can extend ConnectedHoc with new props\n      overrideCount?: number;\n    };\n\n  class Hoc extends React.Component\u003CHocProps> {\n    \u002F\u002F Enhance component name for debugging and React-Dev-Tools\n    static displayName = `withConnectedCount(${BaseComponent.name})`;\n    \u002F\u002F reference to original wrapped component\n    static readonly WrappedComponent = BaseComponent;\n\n    render() {\n      const { count, onIncrement, overrideCount, ...restProps } = this.props;\n\n      return (\n        \u003CBaseComponent\n          {...(restProps as BaseProps)}\n          count={overrideCount || count} \u002F\u002F injected\n          onIncrement={onIncrement} \u002F\u002F injected\n        \u002F>\n      );\n    }\n  }\n\n  const ConnectedHoc = connect\u003C\n    ReturnType\u003Ctypeof mapStateToProps>,\n    typeof dispatchProps, \u002F\u002F use \"undefined\" if NOT using dispatchProps\n    Diff\u003CBaseProps, InjectedProps>,\n    RootState\n  >(\n    mapStateToProps,\n    dispatchProps\n  )(Hoc);\n\n  return ConnectedHoc;\n};\n\n```\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nimport * as React from 'react';\n\nimport { withConnectedCount } from '..\u002Fhoc';\nimport { FCCounter } from '..\u002Fcomponents';\n\nconst FCCounterWithConnectedCount = withConnectedCount(FCCounter);\n\nexport default () => (\n  \u003CFCCounterWithConnectedCount overrideCount={5} label={'FCCounterWithState'} \u002F>\n);\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Redux Connected Components\n\n### - Redux connected counter\n\n```tsx\nimport Types from 'MyTypes';\nimport { connect } from 'react-redux';\n\nimport { countersActions, countersSelectors } from '..\u002Ffeatures\u002Fcounters';\nimport { FCCounter } from '..\u002Fcomponents';\n\nconst mapStateToProps = (state: Types.RootState) => ({\n  count: countersSelectors.getReduxCounter(state.counters),\n});\n\nconst dispatchProps = {\n  onIncrement: countersActions.increment,\n};\n\nexport const FCCounterConnected = connect(\n  mapStateToProps,\n  dispatchProps\n)(FCCounter);\n\n```\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nimport * as React from 'react';\n\nimport { FCCounterConnected } from '.';\n\nexport default () => \u003CFCCounterConnected label={'FCCounterConnected'} \u002F>;\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n### - Redux connected counter with own props\n\n```tsx\nimport Types from 'MyTypes';\nimport { connect } from 'react-redux';\n\nimport { countersActions, countersSelectors } from '..\u002Ffeatures\u002Fcounters';\nimport { FCCounter } from '..\u002Fcomponents';\n\ntype OwnProps = {\n  initialCount?: number;\n};\n\nconst mapStateToProps = (state: Types.RootState, ownProps: OwnProps) => ({\n  count:\n    countersSelectors.getReduxCounter(state.counters) +\n    (ownProps.initialCount || 0),\n});\n\nconst dispatchProps = {\n  onIncrement: countersActions.increment,\n};\n\nexport const FCCounterConnectedOwnProps = connect(\n  mapStateToProps,\n  dispatchProps\n)(FCCounter);\n\n```\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nimport * as React from 'react';\n\nimport { FCCounterConnectedOwnProps } from '.';\n\nexport default () => (\n  \u003CFCCounterConnectedOwnProps\n    label={'FCCounterConnectedOwnProps'}\n    initialCount={10}\n  \u002F>\n);\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n### - Redux connected counter via hooks\n\n```tsx\nimport * as React from 'react';\nimport { FCCounter } from '..\u002Fcomponents';\nimport { increment } from '..\u002Ffeatures\u002Fcounters\u002Factions';\nimport { useSelector, useDispatch } from '..\u002Fstore\u002Fhooks';\n\nconst FCCounterConnectedHooksUsage: React.FC = () => {\n  const counter = useSelector(state => state.counters.reduxCounter);\n  const dispatch = useDispatch();\n  return \u003CFCCounter label=\"Use selector\" count={counter} onIncrement={() => dispatch(increment())}\u002F>;\n};\n\nexport default FCCounterConnectedHooksUsage;\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### - Redux connected counter with `redux-thunk` integration\n\n```tsx\nimport Types from 'MyTypes';\nimport { bindActionCreators, Dispatch } from 'redux';\nimport { connect } from 'react-redux';\nimport * as React from 'react';\n\nimport { countersActions } from '..\u002Ffeatures\u002Fcounters';\n\n\u002F\u002F Thunk Action\nconst incrementWithDelay = () => async (dispatch: Dispatch): Promise\u003Cvoid> => {\n  setTimeout(() => dispatch(countersActions.increment()), 1000);\n};\n\nconst mapStateToProps = (state: Types.RootState) => ({\n  count: state.counters.reduxCounter,\n});\n\nconst mapDispatchToProps = (dispatch: Dispatch\u003CTypes.RootAction>) =>\n  bindActionCreators(\n    {\n      onIncrement: incrementWithDelay,\n    },\n    dispatch\n  );\n\ntype Props = ReturnType\u003Ctypeof mapStateToProps> &\n  ReturnType\u003Ctypeof mapDispatchToProps> & {\n    label: string;\n  };\n\nexport const FCCounter: React.FC\u003CProps> = props => {\n  const { label, count, onIncrement } = props;\n\n  const handleIncrement = () => {\n    \u002F\u002F Thunk action is correctly typed as promise\n    onIncrement().then(() => {\n      \u002F\u002F ...\n    });\n  };\n\n  return (\n    \u003Cdiv>\n      \u003Cspan>\n        {label}: {count}\n      \u003C\u002Fspan>\n      \u003Cbutton type=\"button\" onClick={handleIncrement}>\n        {`Increment`}\n      \u003C\u002Fbutton>\n    \u003C\u002Fdiv>\n  );\n};\n\nexport const FCCounterConnectedBindActionCreators = connect(\n  mapStateToProps,\n  mapDispatchToProps\n)(FCCounter);\n\n```\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nimport * as React from 'react';\n\nimport { FCCounterConnectedBindActionCreators } from '.';\n\nexport default () => (\n  \u003CFCCounterConnectedBindActionCreators\n    label={'FCCounterConnectedBindActionCreators'}\n  \u002F>\n);\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n## Context\n\n> \u003Chttps:\u002F\u002Freactjs.org\u002Fdocs\u002Fcontext.html>\n\n### ThemeContext\n\n```tsx\nimport * as React from 'react';\n\nexport type Theme = React.CSSProperties;\n\ntype Themes = {\n  dark: Theme;\n  light: Theme;\n};\n\nexport const themes: Themes = {\n  dark: {\n    color: 'black',\n    backgroundColor: 'white',\n  },\n  light: {\n    color: 'white',\n    backgroundColor: 'black',\n  },\n};\n\nexport type ThemeContextProps = { theme: Theme; toggleTheme?: () => void };\nconst ThemeContext = React.createContext\u003CThemeContextProps>({ theme: themes.light });\n\nexport default ThemeContext;\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### ThemeProvider\n\n```tsx\nimport React from 'react';\nimport ThemeContext, { themes, Theme } from '.\u002Ftheme-context';\nimport ToggleThemeButton from '.\u002Ftheme-consumer';\n\ninterface State {\n  theme: Theme;\n}\nexport class ThemeProvider extends React.Component\u003C{}, State> {\n  readonly state: State = { theme: themes.light };\n\n  toggleTheme = () => {\n    this.setState(state => ({\n      theme: state.theme === themes.light ? themes.dark : themes.light,\n    }));\n  }\n\n  render() {\n    const { theme } = this.state;\n    const { toggleTheme } = this;\n    return (\n      \u003CThemeContext.Provider value={{ theme, toggleTheme }}>\n        \u003CToggleThemeButton \u002F>\n      \u003C\u002FThemeContext.Provider>\n    );\n  }\n}\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### ThemeConsumer\n\n```tsx\nimport * as React from 'react';\nimport ThemeContext from '.\u002Ftheme-context';\n\ntype Props = {};\n\nexport default function ToggleThemeButton(props: Props) {\n  return (\n    \u003CThemeContext.Consumer>\n      {({ theme, toggleTheme }) => \u003Cbutton style={theme} onClick={toggleTheme} {...props} \u002F>}\n    \u003C\u002FThemeContext.Consumer>\n  );\n}\n\n```\n\n### ThemeConsumer in class component\n\n```tsx\nimport * as React from 'react';\nimport ThemeContext from '.\u002Ftheme-context';\n\ntype Props = {};\n\nexport class ToggleThemeButtonClass extends React.Component\u003CProps> {\n  static contextType = ThemeContext;\n  declare context: React.ContextType\u003Ctypeof ThemeContext>;\n\n  render() {\n    const { theme, toggleTheme } = this.context;\n    return (\n      \u003Cbutton style={theme} onClick={toggleTheme}>\n        Toggle Theme\n      \u003C\u002Fbutton>\n    );\n  }\n}\n\n```\n\n[Implementation with Hooks](#--usecontext)\n\n[⇧ back to top](#table-of-contents)\n\n\n---\n\n# Redux\n\n## Store Configuration\n\n### Create Global Store Types\n\n#### `RootState` - type representing root state-tree\n\nCan be imported in connected components to provide type-safety to Redux `connect` function\n\n#### `RootAction` - type representing union type of all action objects\n\nCan be imported in various layers receiving or sending redux actions like: reducers, sagas or redux-observables epics\n\n```tsx\nimport { StateType, ActionType } from 'typesafe-actions';\n\ndeclare module 'MyTypes' {\n  export type Store = StateType\u003Ctypeof import('.\u002Fstore').default>;\n  export type RootAction = ActionType\u003Ctypeof import('.\u002Froot-action').default>;\n  export type RootState = StateType\u003CReturnType\u003Ctypeof import('.\u002Froot-reducer').default>>;\n}\n\ndeclare module 'typesafe-actions' {\n  interface Types {\n    RootAction: ActionType\u003Ctypeof import('.\u002Froot-action').default>;\n  }\n}\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### Create Store\n\nWhen creating a store instance we don't need to provide any additional types. It will set-up a **type-safe Store instance** using type inference.\n> The resulting store instance methods like `getState` or `dispatch` will be type checked and will expose all type errors\n\n```tsx\nimport { RootAction, RootState, Services } from 'MyTypes';\nimport { applyMiddleware, createStore } from 'redux';\nimport { createEpicMiddleware } from 'redux-observable';\n\nimport services from '..\u002Fservices';\nimport { routerMiddleware } from '.\u002Fredux-router';\nimport rootEpic from '.\u002Froot-epic';\nimport rootReducer from '.\u002Froot-reducer';\nimport { composeEnhancers } from '.\u002Futils';\n\nconst epicMiddleware = createEpicMiddleware\u003C\n  RootAction,\n  RootAction,\n  RootState,\n  Services\n>({\n  dependencies: services,\n});\n\n\u002F\u002F configure middlewares\nconst middlewares = [epicMiddleware, routerMiddleware];\n\u002F\u002F compose enhancers\nconst enhancer = composeEnhancers(applyMiddleware(...middlewares));\n\n\u002F\u002F rehydrate state on app start\nconst initialState = {};\n\n\u002F\u002F create store\nconst store = createStore(\n  rootReducer,\n  initialState,\n  enhancer\n);\n\nepicMiddleware.run(rootEpic);\n\n\u002F\u002F export store singleton instance\nexport default store;\n\n```\n\n---\n\n## Action Creators 🌟\n\n> We'll be using a battle-tested helper library [`typesafe-actions`](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Ftypesafe-actions#typesafe-actions) [![Latest Stable Version](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Ftypesafe-actions.svg)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Ftypesafe-actions) [![NPM Downloads](https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fdt\u002Ftypesafe-actions.svg)](https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Ftypesafe-actions) that's designed to make it easy and fun working with **Redux** in **TypeScript**.\n\n> To learn more please check this in-depth tutorial: [Typesafe-Actions - Tutorial](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Ftypesafe-actions#tutorial)!\n\nA solution below is using a simple factory function to automate the creation of type-safe action creators. The goal is to decrease maintenance effort and reduce code repetition of type annotations for actions and creators. The result is completely typesafe action-creators and their actions.\n\n```tsx\n\u002F* eslint-disable *\u002F\nimport { action } from 'typesafe-actions';\n\nimport { ADD, INCREMENT } from '.\u002Fconstants';\n\n\u002F* SIMPLE API *\u002F\n\nexport const increment = () => action(INCREMENT);\nexport const add = (amount: number) => action(ADD, amount);\n\n\u002F* ADVANCED API *\u002F\n\n\u002F\u002F More flexible allowing to create complex actions more easily\n\u002F\u002F use can use \"action-creator\" instance in place of \"type constant\"\n\u002F\u002F e.g. case getType(increment): return action.payload;\n\u002F\u002F This will allow to completely eliminate need for \"constants\" in your application, more info here:\n\u002F\u002F https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Ftypesafe-actions#constants\n\nimport { createAction } from 'typesafe-actions';\nimport { Todo } from '..\u002Ftodos\u002Fmodels';\n\nexport const emptyAction = createAction(INCREMENT)\u003Cvoid>();\nexport const payloadAction = createAction(ADD)\u003Cnumber>();\nexport const payloadMetaAction = createAction(ADD)\u003Cnumber, string>();\n\nexport const payloadCreatorAction = createAction(\n  'TOGGLE_TODO',\n  (todo: Todo) => todo.id\n)\u003Cstring>();\n\n```\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nimport { store } from '..\u002F..\u002Fstore\u002F';\nimport { countersActions as counter } from '..\u002Fcounters';\n\n\u002F\u002F store.dispatch(counter.increment(1)); \u002F\u002F Error: Expected 0 arguments, but got 1.\nstore.dispatch(counter.increment()); \u002F\u002F OK\n\n\u002F\u002F store.dispatch(counter.add()); \u002F\u002F Error: Expected 1 arguments, but got 0.\nstore.dispatch(counter.add(1)); \u002F\u002F OK\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Reducers\n\n### State with Type-level Immutability\n\nDeclare reducer `State` type with `readonly` modifier to get compile time immutability\n\n```ts\nexport type State = {\n  readonly counter: number;\n  readonly todos: ReadonlyArray\u003Cstring>;\n};\n```\n\nReadonly modifier allow initialization, but will not allow reassignment by highlighting compiler errors\n\n```ts\nexport const initialState: State = {\n  counter: 0,\n}; \u002F\u002F OK\n\ninitialState.counter = 3; \u002F\u002F TS Error: cannot be mutated\n```\n\nIt's great for **Arrays in JS** because it will error when using mutator methods like (`push`, `pop`, `splice`, ...), but it'll still allow immutable methods like (`concat`, `map`, `slice`,...).\n\n```ts\nstate.todos.push('Learn about tagged union types') \u002F\u002F TS Error: Property 'push' does not exist on type 'ReadonlyArray\u003Cstring>'\nconst newTodos = state.todos.concat('Learn about tagged union types') \u002F\u002F OK\n```\n\n#### Caveat - `Readonly` is not recursive\n\nThis means that the `readonly` modifier doesn't propagate immutability down the nested structure of objects. You'll need to mark each property on each level explicitly.\n\n> **TIP:** use `Readonly` or `ReadonlyArray` [Mapped types](https:\u002F\u002Fwww.typescriptlang.org\u002Fdocs\u002Fhandbook\u002Fadvanced-types.html)\n\n```ts\nexport type State = Readonly\u003C{\n  counterPairs: ReadonlyArray\u003CReadonly\u003C{\n    immutableCounter1: number,\n    immutableCounter2: number,\n  }>>,\n}>;\n\nstate.counterPairs[0] = { immutableCounter1: 1, immutableCounter2: 1 }; \u002F\u002F TS Error: cannot be mutated\nstate.counterPairs[0].immutableCounter1 = 1; \u002F\u002F TS Error: cannot be mutated\nstate.counterPairs[0].immutableCounter2 = 1; \u002F\u002F TS Error: cannot be mutated\n```\n\n#### Solution - recursive `Readonly` is called `DeepReadonly`\n\nTo fix this we can use [`DeepReadonly`](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Futility-types#deepreadonlyt) type (available from `utility-types`).\n\n```ts\nimport { DeepReadonly } from 'utility-types';\n\nexport type State = DeepReadonly\u003C{\n  containerObject: {\n    innerValue: number,\n    numbers: number[],\n  }\n}>;\n\nstate.containerObject = { innerValue: 1 }; \u002F\u002F TS Error: cannot be mutated\nstate.containerObject.innerValue = 1; \u002F\u002F TS Error: cannot be mutated\nstate.containerObject.numbers.push(1); \u002F\u002F TS Error: cannot use mutator methods\n```\n\n[⇧ back to top](#table-of-contents)\n\n### Typing reducer\n\n> to understand following section make sure to learn about [Type Inference](https:\u002F\u002Fwww.typescriptlang.org\u002Fdocs\u002Fhandbook\u002Ftype-inference.html), [Control flow analysis](https:\u002F\u002Fgithub.com\u002FMicrosoft\u002FTypeScript\u002Fwiki\u002FWhat%27s-new-in-TypeScript#control-flow-based-type-analysis) and [Tagged union types](https:\u002F\u002Fgithub.com\u002FMicrosoft\u002FTypeScript\u002Fwiki\u002FWhat%27s-new-in-TypeScript#tagged-union-types)\n\n```tsx\nimport { combineReducers } from 'redux';\nimport { ActionType } from 'typesafe-actions';\n\nimport { Todo, TodosFilter } from '.\u002Fmodels';\nimport * as actions from '.\u002Factions';\nimport { ADD, CHANGE_FILTER, TOGGLE } from '.\u002Fconstants';\n\nexport type TodosAction = ActionType\u003Ctypeof actions>;\n\nexport type TodosState = Readonly\u003C{\n  todos: Todo[];\n  todosFilter: TodosFilter;\n}>;\nconst initialState: TodosState = {\n  todos: [],\n  todosFilter: TodosFilter.All,\n};\n\nexport default combineReducers\u003CTodosState, TodosAction>({\n  todos: (state = initialState.todos, action) => {\n    switch (action.type) {\n      case ADD:\n        return [...state, action.payload];\n\n      case TOGGLE:\n        return state.map(item =>\n          item.id === action.payload\n            ? { ...item, completed: !item.completed }\n            : item\n        );\n\n      default:\n        return state;\n    }\n  },\n  todosFilter: (state = initialState.todosFilter, action) => {\n    switch (action.type) {\n      case CHANGE_FILTER:\n        return action.payload;\n\n      default:\n        return state;\n    }\n  },\n});\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### Typing reducer with `typesafe-actions`\n\n> Notice we are not required to use any generic type parameter in the API. Try to compare it with regular reducer as they are equivalent.\n\n```tsx\nimport { combineReducers } from 'redux';\nimport { createReducer } from 'typesafe-actions';\n\nimport { Todo, TodosFilter } from '.\u002Fmodels';\nimport { ADD, CHANGE_FILTER, TOGGLE } from '.\u002Fconstants';\n\nexport type TodosState = Readonly\u003C{\n  todos: Todo[];\n  todosFilter: TodosFilter;\n}>;\nconst initialState: TodosState = {\n  todos: [],\n  todosFilter: TodosFilter.All,\n};\n\nconst todos = createReducer(initialState.todos)\n  .handleType(ADD, (state, action) => [...state, action.payload])\n  .handleType(TOGGLE, (state, action) =>\n    state.map(item =>\n      item.id === action.payload\n        ? { ...item, completed: !item.completed }\n        : item\n    )\n  );\n\nconst todosFilter = createReducer(initialState.todosFilter).handleType(\n  CHANGE_FILTER,\n  (state, action) => action.payload\n);\n\nexport default combineReducers({\n  todos,\n  todosFilter,\n});\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### Testing reducer\n\n```tsx\nimport {\n  todosReducer as reducer,\n  todosActions as actions,\n} from '.\u002F';\nimport { TodosState } from '.\u002Freducer';\n\n\u002F**\n * FIXTURES\n *\u002F\nconst getInitialState = (initial?: Partial\u003CTodosState>) =>\n  reducer(initial as TodosState, {} as any);\n\n\u002F**\n * STORIES\n *\u002F\ndescribe('Todos Stories', () => {\n  describe('initial state', () => {\n    it('should match a snapshot', () => {\n      const initialState = getInitialState();\n      expect(initialState).toMatchSnapshot();\n    });\n  });\n\n  describe('adding todos', () => {\n    it('should add a new todo as the first element', () => {\n      const initialState = getInitialState();\n      expect(initialState.todos).toHaveLength(0);\n      const state = reducer(initialState, actions.add('new todo'));\n      expect(state.todos).toHaveLength(1);\n      expect(state.todos[0].title).toEqual('new todo');\n    });\n  });\n\n  describe('toggling completion state', () => {\n    it('should mark active todo as complete', () => {\n      const activeTodo = { id: '1', completed: false, title: 'active todo' };\n      const initialState = getInitialState({ todos: [activeTodo] });\n      expect(initialState.todos[0].completed).toBeFalsy();\n      const state1 = reducer(initialState, actions.toggle(activeTodo.id));\n      expect(state1.todos[0].completed).toBeTruthy();\n    });\n  });\n});\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Async Flow with `redux-observable`\n\n### Typing epics\n\n```tsx\nimport { RootAction, RootState, Services } from 'MyTypes';\nimport { Epic } from 'redux-observable';\nimport { tap, ignoreElements, filter } from 'rxjs\u002Foperators';\nimport { isOfType } from 'typesafe-actions';\n\nimport { todosConstants } from '..\u002Ftodos';\n\n\u002F\u002F contrived example!!!\nexport const logAddAction: Epic\u003CRootAction, RootAction, RootState, Services> = (\n  action$,\n  state$,\n  { logger }\n) =>\n  action$.pipe(\n    filter(isOfType(todosConstants.ADD)), \u002F\u002F action is narrowed to: { type: \"ADD_TODO\"; payload: string; }\n    tap(action => {\n      logger.log(\n        `action type must be equal: ${todosConstants.ADD} === ${action.type}`\n      );\n    }),\n    ignoreElements()\n  );\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### Testing epics\n\n```tsx\nimport { StateObservable, ActionsObservable } from 'redux-observable';\nimport { RootState, RootAction } from 'MyTypes';\nimport { Subject } from 'rxjs';\n\nimport { add } from '.\u002Factions';\nimport { logAddAction } from '.\u002Fepics';\n\n\u002F\u002F Simple typesafe mock of all the services, you dont't need to mock anything else\n\u002F\u002F It is decoupled and reusable for all your tests, just put it in a separate file\nconst services = {\n  logger: {\n    log: jest.fn(),\n  },\n  localStorage: {\n    loadState: jest.fn(),\n    saveState: jest.fn(),\n  },\n};\n\ndescribe('Todos Epics', () => {\n  let state$: StateObservable\u003CRootState>;\n\n  beforeEach(() => {\n    state$ = new StateObservable\u003CRootState>(\n      new Subject\u003CRootState>(),\n      undefined as any\n    );\n  });\n\n  describe('logging todos actions', () => {\n    beforeEach(() => {\n      services.logger.log.mockClear();\n    });\n\n    it('should call the logger service when adding a new todo', done => {\n      const addTodoAction = add('new todo');\n      const action$ = ActionsObservable.of(addTodoAction);\n\n      logAddAction(action$, state$, services)\n        .toPromise()\n        .then((outputAction: RootAction) => {\n          expect(services.logger.log).toHaveBeenCalledTimes(1);\n          expect(services.logger.log).toHaveBeenCalledWith(\n            'action type must be equal: todos\u002FADD === todos\u002FADD'\n          );\n          \u002F\u002F expect output undefined because we're using \"ignoreElements\" in epic\n          expect(outputAction).toEqual(undefined);\n          done();\n        });\n    });\n  });\n});\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Selectors with `reselect`\n\n```tsx\nimport { createSelector } from 'reselect';\n\nimport { TodosState } from '.\u002Freducer';\n\nexport const getTodos = (state: TodosState) => state.todos;\n\nexport const getTodosFilter = (state: TodosState) => state.todosFilter;\n\nexport const getFilteredTodos = createSelector(getTodos, getTodosFilter, (todos, todosFilter) => {\n  switch (todosFilter) {\n    case 'completed':\n      return todos.filter(t => t.completed);\n    case 'active':\n      return todos.filter(t => !t.completed);\n\n    default:\n      return todos;\n  }\n});\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n## Connect with `react-redux`\n\n### Typing connected component\n\n_**NOTE**: Below you'll find a short explanation of concepts behind using `connect` with TypeScript. For more detailed examples please check [Redux Connected Components](#redux-connected-components) section._\n\n```tsx\nimport MyTypes from 'MyTypes';\n\nimport { bindActionCreators, Dispatch, ActionCreatorsMapObject } from 'redux';\nimport { connect } from 'react-redux';\n\nimport { countersActions } from '..\u002Ffeatures\u002Fcounters';\nimport { FCCounter } from '..\u002Fcomponents';\n\n\u002F\u002F Type annotation for \"state\" argument is mandatory to check \n\u002F\u002F the correct shape of state object and injected props you can also\n\u002F\u002F extend connected component Props interface by annotating `ownProps` argument\nconst mapStateToProps = (state: MyTypes.RootState, ownProps: FCCounterProps) => ({\n  count: state.counters.reduxCounter,\n});\n\n\u002F\u002F \"dispatch\" argument needs an annotation to check the correct shape\n\u002F\u002F  of an action object when using dispatch function\nconst mapDispatchToProps = (dispatch: Dispatch\u003CMyTypes.RootAction>) =>\n  bindActionCreators({\n    onIncrement: countersActions.increment,\n  }, dispatch);\n\n\u002F\u002F shorter alternative is to use an object instead of mapDispatchToProps function\nconst dispatchToProps = {\n    onIncrement: countersActions.increment,\n};\n\n\u002F\u002F Notice we don't need to pass any generic type parameters to neither\n\u002F\u002F the connect function below nor map functions declared above\n\u002F\u002F because type inference will infer types from arguments annotations automatically\n\u002F\u002F This is much cleaner and idiomatic approach\nexport const FCCounterConnected =\n  connect(mapStateToProps, mapDispatchToProps)(FCCounter);\n\n\u002F\u002F You can add extra layer of validation of your action creators\n\u002F\u002F by using bindActionCreators generic type parameter and RootAction type\nconst mapDispatchToProps = (dispatch: Dispatch\u003CMyTypes.RootAction>) =>\n  bindActionCreators\u003CActionCreatorsMapObject\u003CTypes.RootAction>>({\n    invalidActionCreator: () => 1, \u002F\u002F Error: Type 'number' is not assignable to type '{ type: \"todos\u002FADD\"; payload: Todo; } | { ... }\n  }, dispatch);\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### Typing `useSelector` and `useDispatch`\n\n```tsx\nimport { Dispatch } from 'redux';\nimport {\n  TypedUseSelectorHook,\n  useSelector as useGenericSelector,\n  useDispatch as useGenericDispatch\n} from 'react-redux';\nimport { RootState, RootAction } from 'MyTypes';\n\nexport const useSelector: TypedUseSelectorHook\u003CRootState> = useGenericSelector;\n\nexport const useDispatch: () => Dispatch\u003CRootAction> = useGenericDispatch;\n\n```\n\n[⇧ back to top](#table-of-contents)\n\n### Typing connected component with `redux-thunk` integration\n\n_**NOTE**: When using thunk action creators you need to use `bindActionCreators`. Only this way you can get corrected dispatch props type signature like below.*_\n\n_**WARNING**: As of now (Apr 2019) `bindActionCreators` signature of the latest `redux-thunk` release will not work as below, you need to use our modified type definitions that you can find here [`\u002Fplayground\u002Ftypings\u002Fredux-thunk\u002Findex.d.ts`](.\u002Fplayground\u002Ftypings\u002Fredux-thunk\u002Findex.d.ts) and then add `paths` overload in your tsconfig like this: [`\"paths\":{\"redux-thunk\":[\"typings\u002Fredux-thunk\"]}`](.\u002Fplayground\u002Ftsconfig.json)._\n\n```tsx\nconst thunkAsyncAction = () => async (dispatch: Dispatch): Promise\u003Cvoid> => {\n  \u002F\u002F dispatch actions, return Promise, etc.\n}\n\nconst mapDispatchToProps = (dispatch: Dispatch\u003CTypes.RootAction>) =>\n  bindActionCreators(\n    {\n      thunkAsyncAction,\n    },\n    dispatch\n  );\n\ntype DispatchProps = ReturnType\u003Ctypeof mapDispatchToProps>;\n\u002F\u002F { thunkAsyncAction: () => Promise\u003Cvoid>; }\n\n\u002F* Without \"bindActionCreators\" fix signature will be the same as the original \"unbound\" thunk function: *\u002F\n\u002F\u002F { thunkAsyncAction: () => (dispatch: Dispatch\u003CAnyAction>) => Promise\u003Cvoid>; }\n```\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n# Configuration & Dev Tools\n\n## Common Npm Scripts\n\n> Common TS-related npm scripts shared across projects\n\n```json\n\"prettier\": \"prettier --list-different 'src\u002F**\u002F*.ts' || (echo '\\nPlease fix code formatting by running:\\nnpm run prettier:fix\\n'; exit 1)\",\n\"prettier:fix\": \"prettier --write 'src\u002F**\u002F*.ts'\",\n\"lint\": \"eslint .\u002Fsrc --ext .js,.jsx,.ts,.tsx\",\n\"tsc\": \"tsc -p .\u002F --noEmit\",\n\"tsc:watch\": \"tsc -p .\u002F --noEmit -w\",\n\"test\": \"jest --config jest.config.json\",\n\"test:watch\": \"jest --config jest.config.json --watch\",\n\"test:update\": \"jest --config jest.config.json -u\"\n\"ci-check\": \"npm run prettier && npm run lint && npm run tsc && npm run test\",\n```\n\n[⇧ back to top](#table-of-contents)\n\n## tsconfig.json\n\nWe have recommended `tsconfig.json` that you can easily add to your project thanks to [`react-redux-typescript-scripts`](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-scripts) package.\n\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\n{\n  \"compilerOptions\": {\n    \"target\": \"ES6\",\n    \"lib\": [\n      \"dom\",\n      \"dom.iterable\",\n      \"esnext\"\n    ],\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\n    \"src\",\n    \"typings\"\n  ]\n}\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n## TSLib\n\nThis library will cut down on your bundle size, thanks to using external runtime helpers instead of adding them per each file.\n\n> \u003Chttps:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Ftslib>\n\n> Installation  \n`npm i tslib`\n\n\nThen add this to your `tsconfig.json`:\n\n```ts\n\"compilerOptions\": {\n  \"importHelpers\": true\n}\n```\n\n[⇧ back to top](#table-of-contents)\n\n## ESLint\n\nWe have recommended config that will automatically add a parser & plugin for TypeScript thanks to [`react-redux-typescript-scripts`](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-scripts) package.\n\n> \u003Chttps:\u002F\u002Ftypescript-eslint.io>\n\n> Installation\n`npm i -D eslint @typescript-eslint\u002Fparser @typescript-eslint\u002Feslint-plugin`\n\n\n### .eslintrc.js\n\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\nmodule.exports = {\n  root: true,\n  parser: '@typescript-eslint\u002Fparser',\n  plugins: ['@typescript-eslint'],\n  extends: ['react-app', 'react-app\u002Fjest', 'prettier'],\n  rules: { 'import\u002Fno-anonymous-default-export': 0 },\n};\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n## Jest\n\n> \u003Chttps:\u002F\u002Fjestjs.io\u002F>\n\n> Installation  \n`npm i -D jest ts-jest @types\u002Fjest`\n\n### jest.config.json\n\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\n{\n  \"verbose\": true,\n  \"transform\": {\n    \".(ts|tsx)\": \"ts-jest\"\n  },\n  \"testRegex\": \"(\u002Fspec\u002F.*|\\\\.(test|spec))\\\\.(ts|tsx|js)$\",\n  \"moduleFileExtensions\": [\"ts\", \"tsx\", \"js\"],\n  \"moduleNameMapper\": {\n    \"^Components\u002F(.*)\": \".\u002Fsrc\u002Fcomponents\u002F$1\"\n  },\n  \"globals\": {\n    \"window\": {},\n    \"ts-jest\": {\n      \"tsConfig\": \".\u002Ftsconfig.json\"\n    }\n  },\n  \"setupFiles\": [\".\u002Fjest.stubs.js\"],\n  \"testURL\": \"http:\u002F\u002Flocalhost\u002F\"\n}\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n### jest.stubs.js\n\n\u003Cdetails>\u003Csummary>\u003Ci>Click to expand\u003C\u002Fi>\u003C\u002Fsummary>\u003Cp>\n\n```tsx\n\u002F\u002F Global\u002FWindow object Stubs for Jest\nwindow.matchMedia = window.matchMedia || function () {\n  return {\n    matches: false,\n    addListener: function () { },\n    removeListener: function () { },\n  };\n};\n\nwindow.requestAnimationFrame = function (callback) {\n  setTimeout(callback);\n};\n\nwindow.localStorage = {\n  getItem: function () { },\n  setItem: function () { },\n};\n\nObject.values = () => [];\n\n```\n\u003C\u002Fp>\u003C\u002Fdetails>\n\n[⇧ back to top](#table-of-contents)\n\n## Style Guides\n\n### [react-styleguidist](https:\u002F\u002Fgithub.com\u002Fstyleguidist\u002Freact-styleguidist)\n\n[⟩⟩⟩ styleguide.config.js](\u002Fplayground\u002Fstyleguide.config.js)  \n\n[⟩⟩⟩ demo](https:\u002F\u002Fpiotrwitek.github.io\u002Freact-redux-typescript-guide\u002F)\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n# FAQ\n\n\n## Ambient Modules\n\n### Imports in ambient modules\n\nFor type augmentation imports should stay outside of module declaration.\n\n```ts\nimport { Operator } from 'rxjs\u002FOperator';\nimport { Observable } from 'rxjs\u002FObservable';\n\ndeclare module 'rxjs\u002FSubject' {\n  interface Subject\u003CT> {\n    lift\u003CR>(operator: Operator\u003CT, R>): Observable\u003CR>;\n  }\n}\n```\n\nWhen creating 3rd party type-definitions all the imports should be kept inside the module declaration, otherwise it will be treated as augmentation and show error\n\n```ts\ndeclare module \"react-custom-scrollbars\" {\n    import * as React from \"react\";\n    export interface positionValues {\n    ...\n```\n\n[⇧ back to top](#table-of-contents)\n\n## Type-Definitions\n\n### Missing type-definitions error\n\nif you cannot find types for a third-party module you can provide your own types or disable type-checking for this module using [Shorthand Ambient Modules](https:\u002F\u002Fgithub.com\u002FMicrosoft\u002FTypeScript-Handbook\u002Fblob\u002Fmaster\u002Fpages\u002FModules.md#shorthand-ambient-modules)\n\n```tsx\n\u002F\u002F typings\u002Fmodules.d.ts\ndeclare module 'MyTypes';\ndeclare module 'react-test-renderer';\ndeclare module '@storybook\u002Faddon-storyshots'\n\n```\n\n### Using custom `d.ts` files for npm modules\n\nIf you want to use an alternative (customized) type-definitions for some npm module (that usually comes with it's own type-definitions), you can do it by adding an override in `paths` compiler option.\n\n```ts\n{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"paths\": {\n      \"redux\": [\"typings\u002Fredux\"], \u002F\u002F use an alternative type-definitions instead of the included one\n      ...\n    },\n    ...,\n  }\n}\n```\n\n[⇧ back to top](#table-of-contents)\n\n## Type Augmentation\n\nStrategies to fix issues coming from external type-definitions files (*.d.ts)\n\n### Augmenting library internal declarations - using relative import\n\n```ts\n\u002F\u002F added missing autoFocus Prop on Input component in \"antd@2.10.0\" npm package\ndeclare module '..\u002Fnode_modules\u002Fantd\u002Flib\u002Finput\u002FInput' {\n  export interface InputProps {\n    autoFocus?: boolean;\n  }\n}\n```\n\n### Augmenting library public declarations - using node_modules import\n\n```ts\n\u002F\u002F fixed broken public type-definitions in \"rxjs@5.4.1\" npm package\nimport { Operator } from 'rxjs\u002FOperator';\nimport { Observable } from 'rxjs\u002FObservable';\n\ndeclare module 'rxjs\u002FSubject' {\n  interface Subject\u003CT> {\n    lift\u003CR>(operator: Operator\u003CT, R>): Observable\u003CR>;\n  }\n}\n```\n\n> More advanced scenarios for working with vendor type-definitions can be found here [Official TypeScript Docs](https:\u002F\u002Fgithub.com\u002FMicrosoft\u002FTypeScript-Handbook\u002Fblob\u002Fmaster\u002Fpages\u002FModules.md#working-with-other-javascript-libraries)\n\n[⇧ back to top](#table-of-contents)\n\n## Misc\n\n### - should I still use React.PropTypes in TS?\n\nNo. With TypeScript, using PropTypes is an unnecessary overhead. When declaring Props and State interfaces, you will get complete intellisense and design-time safety with static type checking. This way you'll be safe from runtime errors and you will save a lot of time on debugging. Additional benefit is an elegant and standardized method of documenting your component public API in the source code.  \n\n[⇧ back to top](#table-of-contents)\n\n### - when to use `interface` declarations and when `type` aliases?\n\nFrom practical side, using `interface` declaration will create an identity (interface name) in compiler errors, on the contrary `type` aliases doesn't create an identity and will be unwinded to show all the properties and nested types it consists of.  \nAlthough I prefer to use `type` most of the time there are some places this can become too noisy when reading compiler errors and that's why I like to leverage this distinction to hide some of not so important type details in errors using interfaces identity.\nRelated `ts-lint` rule: \u003Chttps:\u002F\u002Fpalantir.github.io\u002Ftslint\u002Frules\u002Finterface-over-type-literal\u002F>  \n\n[⇧ back to top](#table-of-contents)\n\n### - what's better default or named exports?\n\nA common flexible solution is to use module folder pattern, because you can leverage both named and default import when you see fit.  \nWith this solution you'll achieve better encapsulation and be able to safely refactor internal naming and folders structure without breaking your consumer code:\n\n```ts\n\u002F\u002F 1. create your component files (`select.tsx`) using default export in some folder:\n\n\u002F\u002F components\u002Fselect.tsx\nconst Select: React.FC\u003CProps> = (props) => {\n...\nexport default Select;\n\n\u002F\u002F 2. in this folder create an `index.ts` file that will re-export components with named exports:\n\n\u002F\u002F components\u002Findex.ts\nexport { default as Select } from '.\u002Fselect';\n...\n\n\u002F\u002F 3. now you can import your components in both ways, with named export (better encapsulation) or using default export (internal access):\n\n\u002F\u002F containers\u002Fcontainer.tsx\nimport { Select } from '@src\u002Fcomponents';\nor\nimport Select from '@src\u002Fcomponents\u002Fselect';\n...\n```\n\n[⇧ back to top](#table-of-contents)\n\n### - how to best initialize class instance or static properties?\n\nPrefered modern syntax is to use class Property Initializers  \n\n```tsx\nclass ClassCounterWithInitialCount extends React.Component\u003CProps, State> {\n  \u002F\u002F default props using Property Initializers\n  static defaultProps: DefaultProps = {\n    className: 'default-class',\n    initialCount: 0,\n  };\n  \n  \u002F\u002F initial state using Property Initializers\n  state: State = {\n    count: this.props.initialCount,\n  };\n  ...\n}\n```\n\n[⇧ back to top](#table-of-contents)\n\n### - how to best declare component handler functions?\n\nPrefered modern syntax is to use Class Fields with arrow functions  \n\n```tsx\nclass ClassCounter extends React.Component\u003CProps, State> {\n\u002F\u002F handlers using Class Fields with arrow functions\n  handleIncrement = () => {\n    this.setState({ count: this.state.count + 1 });\n  };\n  ...\n}\n```\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n# Tutorials & Articles\n\n> Curated list of relevant in-depth tutorials\n\nHigher-Order Components:\n\n- \u003Chttps:\u002F\u002Fmedium.com\u002F@jrwebdev\u002Freact-higher-order-component-patterns-in-typescript-42278f7590fb>\n\n[⇧ back to top](#table-of-contents)\n\n---\n\n# Contributors\n\nThanks goes to these wonderful people ([emoji key](https:\u002F\u002Fgithub.com\u002Fkentcdodds\u002Fall-contributors#emoji-key)):\n\n\u003C!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->\n\u003C!-- prettier-ignore -->\n| [\u003Cimg src=\"https:\u002F\u002Favatars0.githubusercontent.com\u002Fu\u002F739075?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Piotrek Witek\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Fpiotrwitek)\u003Cbr \u002F>[💻](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=piotrwitek \"Code\") [📖](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=piotrwitek \"Documentation\") [🤔](#ideas-piotrwitek \"Ideas, Planning, & Feedback\") [👀](#review-piotrwitek \"Reviewed Pull Requests\") [💬](#question-piotrwitek \"Answering Questions\") | [\u003Cimg src=\"https:\u002F\u002Favatars3.githubusercontent.com\u002Fu\u002F8602615?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Kazz Yokomizo\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Fkazup01)\u003Cbr \u002F>[💵](#financial-kazup01 \"Financial\") [🔍](#fundingFinding-kazup01 \"Funding Finding\") | [\u003Cimg src=\"https:\u002F\u002Favatars1.githubusercontent.com\u002Fu\u002F366438?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Jake Boone\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Fjakeboone02)\u003Cbr \u002F>[📖](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=jakeboone02 \"Documentation\") | [\u003Cimg src=\"https:\u002F\u002Favatars1.githubusercontent.com\u002Fu\u002F9748762?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Amit Dahan\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Famitdahan)\u003Cbr \u002F>[📖](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=amitdahan \"Documentation\") | [\u003Cimg src=\"https:\u002F\u002Favatars1.githubusercontent.com\u002Fu\u002F98167?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>gulderov\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Fgulderov)\u003Cbr \u002F>[📖](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=gulderov \"Documentation\") | [\u003Cimg src=\"https:\u002F\u002Favatars1.githubusercontent.com\u002Fu\u002F1964212?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Erik Pearson\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Femp823)\u003Cbr \u002F>[📖](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=emp823 \"Documentation\") | [\u003Cimg src=\"https:\u002F\u002Favatars1.githubusercontent.com\u002Fu\u002F5342677?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Bryan Mason\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Fflymason)\u003Cbr \u002F>[📖](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=flymason \"Documentation\") |\n| :---: | :---: | :---: | :---: | :---: | :---: | :---: |\n| [\u003Cimg src=\"https:\u002F\u002Favatars1.githubusercontent.com\u002Fu\u002F119451?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Jakub Chodorowicz\u003C\u002Fb>\u003C\u002Fsub>](http:\u002F\u002Fwww.jakub.chodorowicz.pl\u002F)\u003Cbr \u002F>[💻](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fcommits?author=chodorowicz \"Code\") | [\u003Cimg src=\"https:\u002F\u002Favatars1.githubusercontent.com\u002Fu\u002F7266431?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Oleg Maslov\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Fmleg)\u003Cbr \u002F>[🐛](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fissues?q=author%3Amleg \"Bug reports\") | [\u003Cimg src=\"https:\u002F\u002Favatars0.githubusercontent.com\u002Fu\u002F3393293?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Aaron Westbrook\u003C\u002Fb>\u003C\u002Fsub>](https:\u002F\u002Fgithub.com\u002Fawestbro)\u003Cbr \u002F>[🐛](https:\u002F\u002Fgithub.com\u002Fpiotrwitek\u002Freact-redux-typescript-guide\u002Fissues?q=author%3Aawestbro \"Bug reports\") | [\u003Cimg src=\"https:\u002F\u002Favatars3.githubusercontent.com\u002Fu\u002F14539?v=4\" width=\"100px;\"\u002F>\u003Cbr \u002F>\u003Csub>\u003Cb>Peter Blazejewicz\u003C\u002Fb>\u003C\u002Fsub>](http:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fpeterblazejewicz)\u003Cbr \u002F>[📖](https:\u002F","该项目是关于如何在React和Redux应用中使用TypeScript实现静态类型检查的完整指南。它提供了详细的模式和实践，帮助开发者以函数式风格编写完全类型安全的代码，并通过类型推断减少冗余的类型注解，从而简化长期维护。特别适合需要构建大规模、复杂且类型安全的React与Redux应用程序的场景。项目强调了严格模式下的类型安全性，同时推荐了一些辅助库如typesafe-actions和utility-types来增强开发体验。",2,"2026-06-11 03:26:38","top_topic"]