Gradually Migrating To Typescript

 |  TypeScript, Babel

This article covers how to start using TypeScript modules in an existing project alongside JavaScript modules. If you have a large project, it may not be feasible to move to TypeScript all in one go. Gradually migrating provides more flexibility and allows you to, for example, use TypeScript just for new code or “upgrade” modules when there are changes to existing code.

This articles assumes you’re using webpack with Babel to transpile ES6+ down to ES5. The code for this article is available on the GitHub repo: https://github.com/JonUK/javascript-with-typescript


Steps to configure TypeScript support

  1. Install TypeScript:
    npm install --save-dev typescript

  2. Install the Babel TypeScript preset along with class property support plugin:
    npm install --save-dev @babel/preset-typescript
    npm install --save-dev @babel/plugin-proposal-class-properties

  3. Edit .babelrc to include the new Babel preset and plugin:

{  
  "presets": [  
    ...
    "@babel/typescript"  
  ],  
  "plugins": [
    ...  
    "@babel/proposal-class-properties"  
  ]  
}
  1. Update webpack.config so Babel additionally compiles TypeScript files:
...
{
  test: /\.(js|ts)$/,  
  exclude: /node_modules/,  
  loader: 'babel-loader'  
},
...
  1. Update webpack.config to additionally resolve files with the .ts extension:
...
resolve: {  
  extensions: ['.js', '.ts'],
},
...
  1. Create a tsconfig.json file to provide configuration for the TypeScript compiler:
{  
  "compilerOptions": {  
    /* Basic options */  
    "target": "esnext",
    "module": "commonjs",
    "allowJs": true,
    "noEmit": true, 
    "isolatedModules": true,
  
    /* Strict type-checking Options */
    "strict": true,
  
    /* Module resolution options */
    "moduleResolution": "node",
    "baseUrl": "./src",
  
    /* Advanced options */
    "forceConsistentCasingInFileNames": true
  },  
  "include": ["src"]  
}

Steps for ESLint support

  1. Install the ESLint TypeScript parser and plugin:
    npm install --save-dev @typescript-eslint/parser
    npm install --save-dev @typescript-eslint/eslint-plugin

  2. Add an overrides section to .eslintrc to handle TypeScript files:

{
  ...
  "overrides": [
    {
      "extends": ["plugin:@typescript-eslint/recommended"],
      "files": ["*.ts"],
      "parser": "@typescript-eslint/parser",
      "parserOptions": {
        "project": "./tsconfig.json"
      },
      "plugins": [
        "@typescript-eslint"
      ],
      "rules": {
        "@typescript-eslint/no-inferrable-types": "off",
        "@typescript-eslint/no-explicit-any": "off",
        "@typescript-eslint/ban-ts-ignore": "warn",
        "@typescript-eslint/no-use-before-define": ["error", { "functions": false }],
        "no-invalid-this": "off"
      }
    }
  ]
  ...
}  
  1. Update webpack.config so ESLint additionally checks TypeScript files:
...
{  
  enforce: 'pre',  
  test: /\.(js|ts)$/,  
  exclude: /node_modules/,  
  loader: 'eslint-loader',  
  options: {  
    emitError: true,  
    emitWarning: true,  
    failOnError: true  
  }  
},  
...

Using TypeScript modules (GitHub code example)

Having followed the steps above, you can now add TypeScript files in your project.

To see all this is action, I’ve created an example in GitHub for a simple webpage that calculates the character count, word count and longest word length for some text. The example uses webpack, Babel & ESLint along with Karma and Jasmine for unit tests. Screenshot of word count webpage example

The repository has two branches for before and after the TypeScript support changes:

JavaScript webpage GitHub branch before changes
https://github.com/JonUK/javascript-with-typescript/tree/01_javascript_only

JavaScript and TypeScript webpage branch
https://github.com/JonUK/javascript-with-typescript/tree/02_typescript_support

Review the TypeScript file src/wordCountCalculator.ts and it’s corresponding tests wordCountCalculator_test.js which are still in JavaScript.


Now go forth and add TypeScript support! 😄