Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrating create-react-app from javascript to typescript

I started a react project using create-react-app few months ago and I'm interesting in migrating the project from Javascript to Typescript.

I saw that there is a way to create react app with typescript using the flag:

--scripts-version=react-scripts-ts

But I didn't find any explanation how can I migrate an existing JS project to TS. I need it to be done incrementally so I can work with both .js and .ts files so I can do the transformation over time. Does anyone has any experience with this migration? What are the required steps that should be done to make this work?

like image 971
galvan Avatar asked Nov 27 '17 10:11

galvan


People also ask

Is TypeScript better than JavaScript for React?

React Code and File type in TypeScript vs JavaScript From one glance, it looks like the code from a typical React TypeScript and JavaScript has no difference at all. This is not at all surprising as TypeScript is the father of JavaScript — It is the Superset of JavaScript.

Can you mix JavaScript and TypeScript in React?

The short answer is no. TypeScript is a superset of Javascript and any valid javascript file is a valid TypeScript file.

Can we develop React app using TypeScript?

New App From Scratch If you're building a new app and using create-react-app , the docs are great: You can start a new TypeScript app using templates. To use our provided TypeScript template, append --template typescript to the creation command.


3 Answers

UPDATE: create-react-app version 2.1.0 support typescript so for those of you who are starting from scratch you can use it to create new application with typescript, and according to the documentation it should be done with the following command:

$ npx create-react-app my-app --typescript

For existing projects, after updating to version 2.1.0, add the following packages to your project's dependencies with the following command:

$ npm install --save typescript @types/node @types/react @types/react-dom @types/jest

and then you can simply rename .js to .ts files.


I found a solution to migrate create-react-app from javascript to typescript, this way doesn't require eject.

  1. Create a temporary react project with typescript by running the command create-react-app --scripts-version=react-scripts-ts (Note - requires create-react-app to be installed globally)
  2. In your own project - under package.json file remove the react-scripts
  3. Add react-scripts-ts to your project by running the command yarn add react-scripts-ts or if your are using npm then npm install react-scripts-ts. Or, add "react-scripts-ts": "2.8.0" to package.json.
  4. From the project you created in step 1 copy the files: tsconfig.json, tsconfig.test.json tslint.json to your own project
  5. Under your own project, in package.json, under scripts section, change react-scripts instances to react-scripts-ts (should be under start, build, test and eject
  6. Install the typings for react by installing the following modules using yarn or npm: @types/node, @types/react and @types/react-dom. Put in devDependencies section if using package.json.
  7. Change index.js file name to index.tsx
  8. In your tsconfig.json file add the following configuration: "allowSyntheticDefaultImports": true - for more info

NOTE step 7 might require additional modification depends on what you have in your index.js file (if it depends on JS modules in the project).

Now you can run your project and it might work, for those of you who are getting error that contains You may need an appropriate loader to handle this file type regarding .js files, it happens because babel doesn't know how to load .js file from .tsx files. What we need to do is to change the project configuration. The way I found doing it without running eject is using react-app-rewired package. This package lets you configure external configuration which will be added/override the default project settings. What we'll do is using babel to load these type of files. Let's moved on:

  1. Install the package react-app-rewired using yarn or npm

  2. In your root folder (where package.json is located) create a new file with the name config-overrides.js

  3. Put this code in config-overrides file:

    var paths = require('react-scripts-ts/config/paths')
    
    module.exports = function override(config) {
      config.module.rules.push({
        test: /\.(js|jsx)$/,
        include: paths.appSrc,
        loader: require.resolve('babel-loader'),
        options: {
            babelrc: false,
            presets: [require.resolve('babel-preset-react-app')],
            cacheDirectory: true,
        },
      })
    
      return config
    }
    

Edit package.json so the start/start-js, build, test, and eject scripts use react-app-rewired as shown in the project readme. E.g. "test": "react-app-rewired test --scripts-version react-scripts-ts --env=jsdom".

Now you can start you the project and the problem should be solved. You might need additional modifications depending on your project (additional types and so).

Hope it helps

As suggested here in the comments, it's possible to define: "compilerOptions": { "allowJs": true} in your tsconfig.json file, so you can mix JS and TS without react-app-rewired. Thanks for mention this!

like image 91
galvan Avatar answered Oct 16 '22 19:10

galvan


Create React App v2.1.0 was released today with TypeScript support today. That means you no longer need to eject or use the react-scripts-ts fork; all you need to do if you have an existing Create React App project is install the required packages:

$ npm install --save typescript @types/node @types/react @types/react-dom @types/jest
$ # or
$ yarn add typescript @types/node @types/react @types/react-dom @types/jest

You can then simply rename .js files to .ts files to start using TypeScript.

(If you have an existing app using the create-react-app-typescript fork, here's a tutorial on how to port it to regular Create React App.)

like image 32
Vincent Avatar answered Oct 16 '22 19:10

Vincent


You will need to eject a configuration in order to do that.

After ejecting you need to perform the following steps:

  1. Add typescript extensions tsx and ts to the extensions table in the webpack configs (dev and prod).
  2. Add ts-loader. Here is an example

    {
      test: /\.(ts|tsx)$/,
      include: paths.appSrc,
      use: [
        {
          loader: require.resolve('ts-loader'),
        },
      ],
    },
    
  3. Change eslint to tslint

  4. Add source-map-loader to get a possibility to debug Typescript files.

    {
      test: /\.js$/,
      loader: require.resolve('source-map-loader'),
      enforce: 'pre',
      include: paths.appSrc,
    }
    
  5. Create a Typescript config file and remember to set allowJs to true.

like image 33
niba Avatar answered Oct 16 '22 21:10

niba