Ways and Advantages of Migrating JavaScript Code to TypeScript

Nowadays, more and more new languages are created with the aim of providing an alternative to JavaScript. One of these languages is TypeScript. It is compiled to readable JavaScript code; its main goals are to perform type checking at compile time and to support the object-oriented paradigm. In this post we will not discuss the pros and cons of concrete languages or type systems. Instead, we’ll describe an easy way of performing migrations to TypeScript, and demonstrate how the conversion from JavaScript to TypeScript helps discover interesting artifacts (potential errors) as well as making your code clearer.

Ways Of Migrating

In the JavaScript world, people like to use patterns to represent entities, but unfortunately, these are not supported on the language level with constructs such as classes with inheritance, modules and other sorts of abstraction. There are lots of ways to implement these patterns. Sometimes, this abundance of mechanisms for emulating classical OOP constructs leads to confusion. On the other hand, TypeScript explicitly supports these abstractions in its syntax. This is why the process of converting JavaScript to TypeScript makes your code much clearer. The most straightforward way is, of course, manual conversion (see, e.g., this article), but that takes a lot of time and resources. In this post we try using a semi-automatic tool for this and attempt to assess its advantages and disadvantages.

Using a Semi-Automatic Tool

We took some real-world industrial code: bits of JavaScript that are part of node.js framework. It is about 25k lines of JavaScript code with classes and other constructs. For migration to TypeScript, we used a new ability of ReSharper 9, which performs the transformation of the provided JavaScript code. This feature is capable of handling the following JavaScript patterns:

Internal modules
Immediately-invoked function expressions
Immediately-invoked function expressions with namespace object passed as an argument
External modules
AMD format
CommonJs format
Classes and inheritance
Prototype.js
Native class implementation
Misc
Function expression to lambda
Member assigned by a function expression to function member
Usage of parent class via invocation of call/apply to keyword super
Creating dynamic property to ambient declaration
Recovering types
Infer possible overload signatures by function body/vsDoc

In general, support for these patterns allows ReSharper to very quickly produce an OOP baseline implementation. This is the tool’s main advantage. As a result we get approximate TypeScript code, which requires some error correction before it can be put into production.

So, what errors did we get after performing the conversion? We got about 1,200 errors and, after a certain amount of classification (thanks to ReSharper’s Solution-Wide Analysis) we managed to pinpoint these particular types of errors:

  • “Cannot resolve symbol” and other related errors – 70% of cases

  • “Supplied parameters do not match any signature of call target” – 25% of cases

  • Other cases – 5%

The occurrence of the “lack of matched signature” errors is related to the fact that the inference of overload signatures is not always possible statically without special annotation libraries. See example below.

Original JavaScript code:

JavaScript to TypeScript converter: original JavaScript code

Generated TypeScript code:

JavaScript to TypeScript converter: generated TypeScript code

But this is not the only source of problems. The next example illustrates a more frequent situation:

 

You may notice that the fail function does not declare optional parameters. That is why ReSharper is unable to infer the overload signature with optional parameters. This code can be confusing, and may cause errors.

The most frequent type of error, however, is the inability to resolve a particular symbol, as well as related issues. These also appear because of dynamic nature of the language:

In general, these sorts of errors are expected. At the moment, it is the developer’s responsibility to fix these errors but, in the future, ReSharper might be able to resolve them automatically.

Errors from the other category are more interesting. Some of them shows that the lack of common convention leads to confusing. The next example shows a typical deviation from convention CommonJs modules.

Declaration of Buffer as exported variable:

Usage of the Buffer symbol, which was not imported:

Symbol Buffer is global type, by design, of node.js, but it is not obvious by code.

The next example demonstrates multiple inheritance. If your parent classes have properties with the same name and you don’t notice it, it obviously leads to undefined behavior. The compiler can’t help you either. And if you use multiple inheritance in code, you will have to replace it on composition yourself. TypeScript doesn’t support it.

Original JavaScript code:

multiple inheritance in JavaScript code

Generated Ts code:

multiple inheritance in generated TypeScript code

How To Perform Conversion?

Obsolete code can be converted with ReSharper’s highlightings and the corresponding quick-fixes. There are different granularities for conversion:

  • Element under caret
  • In file
  • In folder
  • In project
  • In solution

Converting JavaScript to TypeScript with ReSharper

In conclusion, this tool speeds up the process of converting JavaScript to TypeScript. Give it a try!

This entry was posted in How-To's and tagged , , . Bookmark the permalink.

16 Responses to Ways and Advantages of Migrating JavaScript Code to TypeScript

  1. Pingback: Dew Drop – February 5, 2015 (#1948) | Morning Dew

  2. MichaelD! says:

    Watch out, CSHTML5 is coming out, which will convert your C# to JavaScript automatically for you (the way it should be). Now you don’t even need TypeScript. 😛

  3. Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1794

  4. Pingback: Dew Drop – February 6, 2015 (#1949) | Morning Dew

  5. Mahesh says:

    good to know this tool supports it.
    Btw, where is the “advantages” of this migration as in the header? I just fooled myself after reading this header. kind of misleading. please fix it.

  6. Edgar says:

    So, how exactly do I convert JS to TS with Resharper 9? That last section isn’t too clear…

    • Vadim Lomshakov says:

      If you have js-style code in *.ts files and this code are recognized as js-pattern (see options ‘Inspection Severity’ -> TypeScript -> ‘Language Usage Opportunities’), it will be highlighted and corresponding quick-fix will appear.
      In the case of *.js files, presently you have to change file’s extension to ‘.ts’.

  7. Daniel Earwicker says:

    @MichaelD! TypeScript’s type system has some advantages over the C#/CLR type system, mostly because it’s structural. Also union types are great.

    • Shawn says:

      I agree with Daniel. As far as compile-to-javascript languages go, C# would not be my first choice. Further, TypeScript is superset of Javascript which is a huge plus. Frankly, I’d choose Scala-to-JS over C# as its object-functional nature is a better fit for JS than C# is.

  8. David Whiteman says:

    Any chance that Typescriptify would be made available as a plugin for IntelliJ IDEA? I would think that would be a tool of interest for those users as well.

  9. Vukasin says:

    TypeScript isn’t only part of Microsoft development platform. It is open source and widely used.

    Typescriptify as plugin is must for other Jetbrains IDEs – on the first place WebStorm.

    I’m missing this feature in InteliJ IDEA / PHPStrorm a lot.

  10. Stephen says:

    I can’t find this in Resharper 10. Did it get removed?

  11. figuerres says:

    evaluating resharper and want to convert to Typescrip but it’s not there…

Leave a Reply

Your email address will not be published. Required fields are marked *