I was wrong about TypeScript. Here is why

When something new is announced, people have a tendency to choose sides. When TypeScript was announced, I wrongfully picked a few key concepts that didn’t resonate with me, then chose my side: against. I’ll try to explain what I thought when TypeScript was announced and how I came to realize that there are great minds behind it who really know how to generate huge benefits without huge sacrifices.

My initial thoughts after TypeScript was announced

When Anders Hejlsberg is working on something, that project automatically has my full attention. He has close to 30 years of experience in building compilers and designing programming languages. You can read more about his involvement in various programming languages on his Wikipedia page.

When I heard he was working on a language that is transpiled (aka source-to-source compiled) to JavaScript, I initially felt disappointed. Microsoft is going the Dart/CoffeeScript route and rejecting the ECMAScript standard. I am not going to learn a new language and forget everything I learned just to express something in a shorter form. There must be something more to that.

I also had bad memories of how Microsoft tried to get Windows developers into Web development by introducing ASP.NET Web Forms. Web Forms abstracted away the core technologies of the Web with mixed results. Is TypeScript aimed towards C# developers that “can’t” learn JavaScript? Is it a new language with features which are familiar to C# developers?

Even with Hejlsberg on the team, I simply could not get excited about TypeScript, and I didn’t dig deeper. I completely missed a few key points of the language and compiler.

Getting immediate benefits from TypeScript

In a recent client project, TypeScript was used with React and Redux. I was familiar with both React and Redux, and I had been writing modern JavaScript (ECMAScript 2016, aka ES6) for six months.

Technical note: Text editor plugins use one part of the TypeScript compiler’s API: Language Service. Language Service is designed for text editing when low-latency feedback for the developer is crucial. They provide beautiful API methods like getCompletionsAtPosition, which is used in the example above.

TypeScript with third party libraries

We haven’t written any TypeScript yet, only ES5 source code in a file that has the .ts extension. We can get even more benefits from the compiler by getting the API description to the third party libraries. The API description is called Type Definition in TypeScript.

Let’s download a popular view library, React, and type definitions for it. You can identify type definition files by the “d” in the filename, for example, react.d.ts.

The “dt” refers to the source location of the type definition; it can be npm or a popular site called Definitely Typed (dt), for example. A list of sources can be found here.

Type definitions are installed with the install command.

typings install dt~react dt~react-dom --save

The flag — save has behavior that’s similar to npm’s — save flag: it saves the type definition reference to typings.json.

We are still missing React itself, which can be installed with npm:

npm install react react-dom --save

What is development like now that we have the third party library and its Type Definition file? I made an example with React component with two properties and observed how autocomplete works when I use or edit the component.

In the example, I added my first snippet of TypeScript, the interface declaration. I am not keen on adding types in every situation, but describing the public-facing entry points (such as the component’s properties) is beneficial.

Benefits of type definitions

Now that you don’t have to remember or peek at the API definition, using the API is easier. Refactoring is also much easier.

Imagine that we have a DemoComponent that is used inside many other components and needs different properties. For example, it has a name property that must be changed to something more specific (username, surname, fullName, applicationName, etc.). If you search and replace with the keyword ‘.name’ in a large project, simply put, you’re screwed. You have to check each occurrence for the correct context. When types are used in the correct places, the name property has more semantic meaning and, therefore, the tool knows which names will be affected by refactoring.

The example is simple, but you can imagine a similar operation in a large codebase.

Misconceptions about types

When you hear the word “strongly typed,” it is easy to think that you need to put types everywhere, like in old (before type inference, more on that later) C# or Java code:

IDictionary<int, Car> carsById = new Dictionary<int, Car>();

Lots of noise without much benefit.

TypeScript has a feature called type inference; when I type

let name = "tatu"
name = 2; // an error

I don’t have to explicitly say that name is a type of String: it can be inferred.

There is also a feature called Contextual Type. Here is an example from the documentation:

MouseEvent doesn’t have a type defined, but TypeScript can still throw an error when MouseEvent doesn’t have a property called button. How is this possible?

TypeScript knows that the callback on onmousedown should be a function that accepts a type of MouseEvent. MouseEvent’s type doesn’t have the property button. This kind of check will save time without any effort from the developer!

Using TypeScript with other tools

When I think about other tools that I have used for JavaScript development, the following come to my mind: linting tools, Browserify/Webpack, testing frameworks, and BabelJS. Is TypeScript making some of them obsolete?

Linting tools

If TypeScript is so powerful when it comes to catching errors, do we need tools like ESLint or JSHint? The answer is “yes.” For example, in addition to error checks, ESLint contains stylistic and best practice code format checks. Unfortunately, compatibility with ESLint relies on the TypeScript ESLint Parser project, which is in the experimental stage.

The good news is that there is a tool called TSLint that was created for TypeScript.

Browserify/Webpack

TypeScript is not a bundling tool. For example, if you have your own code in TypeScript and you’re using the lodash 3rd party library in the browser, TypeScript won’t fetch lodash for you to bundle it into a single file. Bundling is the purpose of Browserify/Webpack.

Testing frameworks

I have written tests in TypeScript, compiled to JavaScript, and then used Mocha, for example, to run tests. I would like to hear your thoughts on this.

BabelJS

Can we ditch BabelJS since TypeScript supports ES2016 features? The answer is: it depends. I asked wiser people what benefits BabelJS provide:

@_Tx3 TypeScript can’t currently compile async/await to ES5. If you need that, you need Babel or something else.

In other words, TypeScript supports async/await, but can’t compile it to the ECMAScript version that all browsers understand.

If you don’t use that feature, then please feel free to remove BabelJS from your build process.

Update: Reader, Birk Skyum, pointed out that support for ES3 compilation is on the roadmap and will be released in the version 2.0.

When to use TypeScript

Almost every TypeScript blog post mentions that TypeScript is meant for large projects. From Anders Hejlsberg’s interview on JavaScript Jabber (30:50):

If you’re writing five lines of code, it is probably not worth of the effort … the larger the project gets, the more valuable it is. Like I said earlier, by the time you get to a couple of thousand lines of code, it’s a slam dunk*.

* I had to Google “slam dunk.” It seems to be a basketball term for an easy shot, one that is difficult to miss.

Conclusion

I hope I was able to give you at least a small part of my enthusiasm so that you give TypeScript another chance. I would like to hear whether you have had successful or miserable experiences using TypeScript in real projects. Until next time!