Adding typescript to the existing react project
Tags: react, typescript, javascript, webdev
Published: 2022-08-30 09:07:00

This note will help you understand how to add typescript to an existing Create React App project and start writing new files in the typescript. I use npm as the package manager, but it will not be a problem for you to use yarn or some other way.

If you do not use Redux, do only steps numbered as 1, 2 and 7 only.


###Main steps

1) Let’s install required packages via terminal[1]
 ```
npm i --save typescript @types/node @types/react 
npm i --save @types/react-dom @types/jest
npm install --save-dev @tsconfig/node16
npm i @typescript-eslint/parser
```
2) Create tsconfig.json file manually or with terminal command and fill it with my example of the file

```
tsc --init
```

```
{
 "$schema": "https://json.schemastore.org/tsconfig",
 "display": "Node 16",
 "extends": "@tsconfig/node16/tsconfig.json",
 "compilerOptions": {
   "target": "ES2022",
   "lib": [
     "dom",
     "dom.iterable",
     "ES2022"
   ],
   "allowJs": true,
   "skipLibCheck": true,
   "esModuleInterop": true,
   "allowSyntheticDefaultImports": true,
   "strict": true,
   "forceConsistentCasingInFileNames": true,
   "noFallthroughCasesInSwitch": true,
   "module": "es2022",
   "moduleResolution": "node",
   "resolveJsonModule": true,
   "isolatedModules": true,
   "noEmit": true,
   "jsx": "react-jsx",
   "typeRoots": [
     "src/@types"
   ]
 },
 "include": [
   "src"
 ]
}
```

`$schema`, `display` and `extends` do not set anything to the tsconfig file. They only lead to the online list of options with values, which can be present in the tsconfig.json. In other words, you will have to add configuration by looking at the scheme[2][3].

My IDE changes module from the `es2022` to `esnext`. Do not worry, if you will see this in the notification panel of your IDE.

`typeRoots` contain a path to the file with the default useSelector app state (explanation you can find later). Erase typeRoots from the file, if you do not use Redux.

3) Skip this step, if you do not use Redux. 

It is time to change react-redux index filename extension from `.js` to `.ts` (your file can have another name). After that replace

```
export default combineReducers({
   ...yourReducers
});
```

with

```
export const reducers = combineReducers({
   ...yourReducers
})

export type AppState = ReturnType<typeof reducers>;
```

Explanation of the AppState purpose will be later

4) This section is needed for the developers, which utilize Redux. 

Modify file `store.js` (your implementation file can have another name). You will have to replace

```
import reducers from './reducers';
```

with

```
import { reducers } from './reducers/index.ts';
```

5) Please, ignore this step, if you do not use redux. 

And current step requires creation of the file `react-app-env.d.ts` (`src/react-app-env.d.ts`)[4]

```
/// <reference types="react-scripts" />
```

6) Well, this file is not needed for the not-redux users

Add file under path `src/@types/react-redux.d.ts` with next code

```
import 'react-redux';

import { AppState } from '../reducers';

declare module 'react-redux' {
   interface DefaultRootState extends AppState {}
}
```


Despite AppState being not used anywhere else, it allows not to import reducers app state in the useSelector method every time and the method always know the it’s argument type return value[5]. 

7) Well, modify ESlint file as the last step:

- Change parser

```
"parser": "@typescript-eslint/parser",
```


- Change parser options

```
"parserOptions": {
   "ecmaVersion": "latest",
   ...rest code
}
```


- Update env

```
"env": {
   "es2021": true,
   ...rest code
}
```


- Modify rules for disabling warnings or errors for unused code (by your choice only), removing mistake about typescript file extensions (code will work without this rule, but you will see unpleasant message) and remove warning about lack of default props

```
"rules": {
   "no-use-before-define": "off",
   "react/jsx-filename-extension": [2, { "extensions": [".js", ".jsx", ".ts", ".tsx"] }],
   "react/require-default-props": "off"
}
```

###Conclusion
I have to warn you, that file import with .ts and .tsx extensions is obligatory now (you can ignore it only in the created by create-react-app application). As a disadvantage, live reloading can be broken and you will have to reload the page manually every time.

###Sources
[1] [Adding TypeScript](https://create-react-app.dev/docs/adding-typescript/)
[2] [What is a tsconfig.json](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html#tsconfig-bases)
[3] [tsconfig.json base configuration](https://json.schemastore.org/tsconfig)
[4] [What is the react-app-env.d.ts in a react typescript project for](https://stackoverflow.com/questions/67262914/what-is-the-react-app-env-d-ts-in-a-react-typescript-project-for)
[5] [TS2339: Property 'tsReducer' does not exist on type 'DefaultRootState'](https://stackoverflow.com/questions/60777859/ts2339-property-tsreducer-does-not-exist-on-type-defaultrootstate)