Migrating your React boilerplate project from using Flow to Typescript
This particular set of instructions are for those who wish to migrate their react app created from React-Boilerplate-Flow to use Typescript instead of flow.
I use vscode for my work and there are certain instruction that ask you to do stuff in vscode, just do the same using whatever editor you want. I recommend vscode
-
Remove '.flowconfig' and 'flow-typed'
you dont need these anymore as you are getting rid of flow
-
Remove flow-bin from dependencies
Go to package.json and remove the dependencie relating to flow. Starting with flow-bin
-
Add Typescript to dependencies
I used version 3.8 and the instructions may differ for some versions
-
Add tsconfig.json (opens in a new tab) to / from react-boilerplate-typescript
React-Boilerplate already had typescript version. It will be easier if you just copy the file first an then modify. You dont have to start from scratch this way. Make the following changes
- set
compilerOptions.incremental=true
"include": ["app/**/*"]
"exclude": ["node_modules", "internals/templates/\*\*/*", "app/\*\*/*.test.*"]
- set
-
Add "@babel/preset-typescript", "@typescript-eslint/eslint-plugin", "@typescript-eslint/parser" to dependencies, update eslint
Use the package manager to add the required dependencies. Might as well update eslint to work well with the newly added dependencies
-
Remove "@babel/preset-flow", "babel-preset-flow", "eslint-plugin-flowtype" dependencies
These were used by flow and are not required anymore
-
Modify .eslintrc to use @typescript-eslint
parser: @typescript-eslint.parser
extends: ['airbnb-typescript', 'prettier', 'prettier/react', 'prettier/@typescript-eslint'],
plugins: ['prettier', 'redux-saga', 'react', 'react-hooks', 'jsx-a11y', '@typescript-eslint'],
parserOptions: { project: './tsconfig.json', },
-
Update babel config
- change
'@babel/preset-flow',to '@babel/preset-typescript',
- change
-
Prepare the codemod
The existence of this codemod is what made us optimistic about the migration. Last I used the codemod It neede some tweaking. The major issue was git detects the file extension change as delete and add, which will cause the project to lose commit history of the affected file. Also the codemod uses prettier on the project but the version of prettier used by the codemod doesnt support optional chaining syntax and throws errors
- clone the @khanacademy/flow-to-ts (opens in a new tab) github repo,
- modify cli.js: update the input files and do git mv instead of creating new ts files
- update prettier to parse optionalChaining syntax
-
Run the codemod
node path\to\flow-to-ts.js --prettier --semi --single-quote --tab-width 2 --bracket-spacing --print-width 80 --write --delete-source app/**/*.js
-
Search and replace 'Object' to 'any'
You shouldnt have had these types in your flow-typed project in the first place. If you dont, you can skip this step, otherwise make this change in every concerned file. VS code will help yo with this
-
Search and replace @flow annotations that survived the codemod
The codemod fill strip away most @flow annotations but some may still persist becuase the formatting might've been different from what the codemod was looking for
-
Run
prettify
-
Remove vscode extensions for flow
-
Update file references
The codemod will have changed file extensions. Update all file references that point to the old .js or .jsx fieles
- webpack -- entry: app.tsx -- resolve: .ts and .tsx files as well -- test: /.[j|t]sx?$/ for babel-loader
- package.json -- lint-staged, use "*.{js,jsx,ts,tsx}" pattern
- .gitattributes
-- add
*.ts text eol=lf
and*.tsx text eol=lf
-
Modify .eslint if eslint was updated and you didnt have these configured
'react/prop-types': 0, 'react/jsx-props-no-spreading': 0, 'react/jsx-curly-newline': 0, 'react/jsx-curly-newline': 0,
-
Add missing type definitions
Create app/types/assets.d.ts (https://webpack.js.org/guides/typescript/#importing-other-assets (opens in a new tab)) and add the following lines
declare module '*.svg' { const content: any; export default content; } declare module '*.png' { const content: any; export default content; }
-
Update prettier to >1.19 to work with ts
-
Update jest and jest.config
-
utility-types
$Values
and other flow utility types are not available in ts, codemod suggests utility-types package, search for files with 'utility-types' imports and manually implement the same functionality using ts --$Values
can be replaced by usingenum
in ts -
update storybook to work with typescript
If your project uses storybook do these steps as well
- update version to ^5.3
- search and replace incorrect file extensions
- add custom webpack config
module.exports = { stories: ['../app/**/*.stories.tsx'], webpackFinal: async config => { config.module.rules.push({ test: /\.(ts|tsx)$/, loader: require.resolve('babel-loader'), options: { presets: ['@babel/preset-react','@babel/preset-typescript'], }, }); config.resolve.extensions.push('.ts', '.tsx'); return config; }, };