# JavaScript to TypeScript Migration

## Summary


Large projects can benefit from migrating their JavaScript code to TypeScript. Due to TypeScript's support for static types and good tooling, type-related problems can be caught during development and at compile time. However, migrating a large codebase can be a daunting task but this is easier than imagined in TypeScript.

Since TypeScript is a superset of JavaScript, the TypeScript compiler can deal with JavaScript files as well, leaving them untouched and skipping type checks. This means that migration can happen incrementally, file by file. Tools are available to refactor code during the migration process.

It's also been observed that the workflow for TypeScript projects is lot easier now than what it used to be. This means that TypeScript can be adopted for even small projects.

## Discussion

### Could you share some case studies of JS-to-TS migration?

Lucidchart migrated their entire codebase of 600k lines across 2840 files in just three days, resulting in 500k lines of TypeScript code. About 80% of the conversion was aided by tools. They made a dependency graph in a spreadsheet, started converting from the leaves and moved up file by file. At each step, they checked that TS files compiled successfully. After pushing to production, the team expected issues to arise but none were reported. 

One developer reported that his code size (involving 180+ files) increased 30% when moving from JavaScript to TypeScript. In general, this may be acceptable in large projects where the benefits of type checking are far greater. 

The fact that all JavaScript is valid in TypeScript was seen in a Dojo-AMD project. AMD module imports were converted to ES6-style understood by TypeScript. Loading of plugins and exporting of modules were updated. Otherwise, no additional changes were required. 


### What's the recommended procedure for migrating my JavaScript codebase to TypeScript?

The simplest approach is to create a new TypeScript project and add all legacy JavaScript code into it. TS compiler will understand JS source code, although without the type checking. This is possible due to `allowJs` option. Any new files that you create should be in TypeScript. 

You can start adding type checking to existing JS files using type declaration files, of extension `*.d.ts`. Use the `types` option when invoking the TS compiler. At a later stage, you can refactor your JS files into TS files, at which point type declaration files become redundant. 

Gradually, legacy code can be migrated. Simply rename `*.js` files to `*.ts` files. Then start introducing type declarations in the legacy files, although TypeScript's type inference can resolve types in most cases. Linting can throw up a lot of issues when JS files are renamed to TS files. One approach is to disable linting by adding `// tslint:disable` at the start of all legacy files. Then, enable linting file by file when you start working on them. 


### Do you have any tips for refactoring JS code to TS?

Since TypeScript is object-oriented, convert function constructors to class constructors. Give member variables explicit access modifiers. Use `public` but you can restrict access using `protected` or `private`. Replace instance methods with arrow methods, which will use `this` reference to the object. Replace prototype methods with methods. 

To pass TS compilation, you may be tempted to use `any` type: avoid doing this. However, since migration is often incremental, allow TypeScript to automatically infer the `any` type if type is not specified. You can suppress this behaviour later using the `noImplicitAny` option. 

Legacy code might contain runtime type checks and related exception handling. Because now type checking is done at compile time, these extra bits of code can be removed. This can even improve performance. 

When migrating security code, it's recommended that critical code be migrated to TS first. App and third-party code can be migrated later.


### What extra configuration should I do in a TypeScript project?

JavaScript executes directly within a JS runtime. This is not possible with TypeScript. TypeScript files have to converted to JavaScript (called *transpilation*) before they can be executed. Hence a TypeScript project must be set up to automate this conversion.

**Webpack** can be set up with a config file `webpack.config.js`. This can make use of `ts-loader` to load TS files and `json-loader` for JSON files. Type declarations for third-party JS modules can be installed from **@types**. For example, to install "prompt-sync" you can do `npm install --save-dev @types/prompt-sync`. Another possible loader to use is `awesome-typescript-loader`. This can be combined with `source-map-loader` to assist source level debugging. 

Note that it's common for JavaScript projects to use a transpiler to convert between different versions of JavaScript. This is particularly true on the web where code has to run correctly on old browsers. If your JS project is already setup to do this, migrating to TS is even easier. For example, a React project might be using Webpack and Babel. This can be reconfigured so that Webpack reads the output of TypeScript compiler rather than the original JS code. 


### As a beginner, should I learn JavaScript before moving on to TypeScript?

TypeScript is a superset of JavaScript. It doesn't hide JavaScript syntax. For this reason, beginners are encouraged (but not required) to learn JavaScript. In fact, TypeScript shouldn't be used to bring non-JS developers to the frontend. 

Before migrating to TypeScript, it's good to ask what's the background of those who will be working on it. In one instance, a team of C# developers could quickly learn TypeScript for frontend work. In fact, developers with a background in object-oriented programming will be able to pick up TypeScript easily. 


### Are there tools to automate JS-to-TS migration?

Back in 2015, JetBrains described how easy it is to use **ReSharper 9** tool to perform conversions. Some of the limitations of the tool are possibly removed in later updates. The tool allows us to convert a file, an entire folder, a project or a solution. 

Npm package js-to-ts-converter may also help. Airbnb's ts-migrate may also help to automate the migration. However, a manual follow-up is needed to improve type safety. 

If you're using Closure-annotated JS, **gents** (open sourced by Google) can be used to convert to TypeScript. Related tools are clutz and tsickle.

## Milestones

Feb  
2016

TypeScript 1.8 starts supporting compiler option `allowJs`. This makes it easier to directly use JS files within a TypeScript project. TypeScript compiler will do basic sanity checks on JS files but otherwise pass them to the output.  

Jul  
2016

Type definitions are now available via NPM at `@types`. This deprecates earlier approaches: DefinitelyTyped, TSD, Typings. As on April 2019, more than 6,300 packages have type definitions.

Dec  
2018

**Babel 7** is released with support for TypeScript. This means that TypeScript can be transpiled to JavaScript using Babel. Thus, TypeScript-based projects can continue to benefit from Babel's rich ecosystem and plugins. TypeScript compiler can still be used for type checking.