Migrate your project from Javascript to TypeScript
Tags: javascript, typescript, development, webdev
Published: 2023-07-19 08:53:44

We live in a world where technology changes in the blink of an eye every day. Sometimes it becomes essential to step up from the currently used technology. But that comes with a cost, lots of time — effort — and, of course, in some cases, money.
In this article, we will discuss one of that transitions about migrating a project from JavaScript to TypeScript.
Before we proceed, let's briefly understand what a typescript is.
The official documentation of TypeScript states, TypeScript is a strongly typed programming language that builds on JavaScript, giving you better tooling at any scale. TypeScript double ensures that the project is type-safe, which is the first step in the quality of the project.

[https://www.typescriptlang.org/](url)

If we want to follow the conventional steps, we can better refer to the documentation from the typescript itself. Here is the link which you can follow https://bit.ly/3ngsA4G
Before we go on a traditional way to migrate our project, there is a more innovative way.
Airbnb has developed a free tool that can do the heavy lifting for us. Here is the link, if you are interested http://bit.ly/3K4iVa5
But before we use that tool, remember
ts-migrate is intended to accelerate the TypeScript migration process. The resulting code will pass the build, but a follow-up is required to improve type safety. There will be lots of // @ts-expect-error, which must be fixed over time. In general, it is a lot nicer than starting from scratch.

Let's start!

1. Make a new branch
`git checkout -b feature/ts-migrate`

2. Let's install the package
`$ yarn add -D ts-migrate` 
or
`$ npm install --save-Dev ts-migrate`

3. Now, for this article's sake, we would target the src folder
`npx ts-migrate-full src`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/33ralh2bck0qxs35uejk.jpg)

Before the package was installed, we can see in the below figs. all the files were in js format.
You press “y”, and let the package do its magic. If everything goes fine, the package(ts-migrate) will convert .js -> .ts and .jsx ->.tsx and create a tsconfig.json file and .eslintrc.js file for you.

**If it doesn’t go okay, here are a few things that you might want to check:**
a. Please re-ensure all the mentioned steps in the above screenshots are satisfied, or else you might get an error.

b. Check if TypeScript is indeed installed globally.

c. If you are using a mac, there is a chance you need to install the Xcode command line. Go to your terminal and paste this. More on this link

`xcode-select --install`

**Results:**

**Before migration**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k8gf7mh5yoz7o6g4j4qa.png)

**After Migration**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wg8zhypx8l015pjdoxyy.png)

**Correct ts with error codes**
ts-migrate will use different ts-error codes to fix the errors in the project, and we need to fix all of them; for example, they might look something like this:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6f8j1lg5lfh20g9wbe28.png)


Sometimes you may find some of the types in your code are defined as “any,” which is entirely justified, as the ts-migrate has no idea what is the role of some variables in your code, so we also need to fix those wherever necessary.

**Modify webpack.config.js**
This project is using webpack to bundle js files, but now files are .ts, or .tsx so we need to modify webpack configurations.
The most important thing is to switch from .js to .tsx or .ts

For example, entry, extensions and using ts-loader etc.

```
/* eslint-disable @typescript-eslint/no-var-requires */
const path = require('path');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development',
  entry: './src/index.tsx',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    chunkFilename: '[id].js',
    publicPath: '',
  },
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './',
    open: true,
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
      },
      // {
      //     test: /\.(gif|png|svg|jpg)$/,
      //     loader: "url-loader"
      // },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.css$/,
        exclude: /node_modules/,
        use: [
          { loader: 'style-loader' },
          {
            loader: 'css-loader',
            options: {
              modules: {
                localIdentName: '[name]__[local]___[hash:base64:5]',
              },
              sourceMap: true,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [autoprefixer({})],
            },
          },
        ],
      },
      {
        test: /\.(svg|png|jpe?g|gif)$/,
        loader: 'url-loader?limit=10000&name=img/[name].[ext]',
      },
    ],
  },
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.json'],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: __dirname + '/public/index.html',
      filename: 'index.html',
      inject: 'body',
    }),
  ],
};
```

Remember, if you are using any other kind of web bundler, please go through the documentation and change it accordingly.

**Update npm script**
We also need to add .ts and .tsx as a target file like the one below.

```
 "scripts": {
    ...
    "lint": "eslint 'src/**/*.{ts,tsx}'",
    "lint:prettier": "prettier --check './src/**/*.{js,ts,tsx}'"
  }
```

**One more thing… packages that don’t support typescript**
Now there will be certain npm packages that don’t support typescript. For that condition, you can follow these steps:
1. create a folder with the name @types
2. create a file called global.d.ts
3. now, for all the packages which don’t support typescript, you can with something like this:

```
declare module 'react-dom';
declare module 'react-router-dom';
```

**Conclusion**
ts-migrate is quite a valuable tool to make your life easy. It sometimes needs some tweaks here and there, but give it a try at least, which, if successful, can save a lot of hard work and time.