Incrementally migrate your webpack project to TypeScript

TL;DR

If you want to migrate to TypeScript but don’t want to migrate all your code at the same time you can configure webpack to bundle both TypeScript and JavaScript code.

You can find a demo project here.

How to?

To add TypeScript to a webpack project you can follow these steps:

Install the needed dev-dependencies:

npm install --save-dev @types/jest awesome-typescript-loader typescript @types/lodash

Create a tsconfig.json file to specify that you want to transpile to ES6:

{
"compilerOptions": {
"target": "es6"
}
}

Add awesome-typescript-loader to your webpack config file and load your TypeScript first through the TypeScript transpiler and then through Babel:

module: {
rules: [
{ test: /\.jsx?$/, exclude: /node_modules/, use: "babel-loader" },
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: ["babel-loader", "awesome-typescript-loader" }
]
}

To stop Babel from transforming ES6 module syntax to commonjs you need to update the .babelrc file:

{
"presets": [["es2015", { "modules": false }], "react"],
"plugins": ["transform-class-properties"]
}

Now comes the tricky part: keeping the Jest tests running.
Some extra configuration is necessary to tell Jest to transpile TypeScript and to have the normal JavaScript run through Babel-Jest.

In your package.json add the following Jest config:

"jest": {
"moduleFileExtensions": ["ts", "tsx", "js", "jsx"],
"transform": {
"^.+\\.(ts|tsx)$": "<rootDir>/preprocessor.js",
"^.+\\.(js|jsx)$": "babel-jest"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js|jsx)$"
}

Create a preprocessor.js file to transpile TypeScript tests:

const tsc = require("typescript");
module.exports = {
process(src, path) {
if (path.endsWith(".ts") || path.endsWith(".tsx")) {
return tsc.transpile(src, {}, path, []);
}
return src;
}
};

In .babelrc you need to add a separate configuration for the test environment to play nice with Jest:

{
"presets": [["es2015", { "modules": false }], "react"],
"plugins": ["transform-class-properties"],
"env": {
"test": {
"presets": ["es2015", "react"],
"plugins": ["transform-class-properties"]
}
}
}

Now you should be able to start migrating files one by one to TypeScript without breaking tests or builds.