TypeScript vs JavaScript: differences and migration

JavaScript: a brief introduction of the well-known scripting language

As opposed to Java, the statically-typed programming language which constitutes a huge part of the JVM ecosystem, (and BTW used to be used in browsers), JavaScript was intended to be a simple scripting language used primarily for web development and implementing straightforward user interaction handlers. It’s a pretty old story so nowadays, some of you may not even remember these beautiful, reactive pages.

However, as is usually the case with programming languages, JavaScript has followed the evolution of the ECMA standards and has come a long way since the days of its inception. To prove my point, let me just mention frameworks and libraries like Vue, React or Angular, all of which use JavaScript for much more than just simple scripting. The question remains, however, is this originally “simple scripting language” whose aim was to be as simple as pie capable of doing all the demanding tasks effectively?

Looking for the answer to this question, take a glance at two well-known scenarios:

"1" - - "1" = 2
"1" + 1 = "11"
"1" - 1 = 0
"1" + "1" - "1" = 10[Object object] is not a function
Cannot read property 'x' of undefined

Even though they may seem irrational and cause errors sometimes, these behaviors were introduced to make dev’s lives easier. If you’d like to read about more JavaScript-sauced WTF moments, click here – amusement guaranteed ;)

Hungry for more? Read other JavaScript-themed articles by our devs:

TypeScript vs JavaScript: a few facts (which you might have not heard about) about the JS superset

In the previous paragraph, I mentioned something called ECMA standards or ECMAScript (to be precise, ECMA-262). It’s an ECMA International-standardized specification for scripting languages; mostly for JavaScript although it applies to technologies like ActionScript, JScript, and CoffeeScript as well. Bearing that in mind, we could say that JavaScript is just an implementation of ECMA implementation. And that’s where TypeScript enters and the real magic happens.

As opposed to JavaScript, TypeScript is not just an implementation of ECMA standards but primarily a superset of JS. In practice, it means that any program written in JS is valid in TS as well, at least syntactically. We could go so far as to say that TypeScript is basically JavaScript-enhanced with additional useful features.

It seems that TypeScript is doing pretty well in the dev community all around the world. Don’t take my word for it – have a look at an excerpt from the last year’s Stack Overflow Survey:

Stack Overflow Developer Survey 2019

As you can see, TypeScript is one of the three most loved programming languages. And as far as the dreaded technologies are concerned, the JavaScript superset is… the least fearsome to programmers!

The State of JavaScript Survey gives us an even greater insight into the historic popularity of TypeScript. If you observe the annual increase in the number of developers who would use this language again and compare it to the number of devs who would not, you’ll see that the odds are in TypeScript’s favor.

The State of JavaScript Survey 2019

At this point I’d also like to stress that TypeScript is no newbie: it boasts a mature environment as well as generous support among many popular libraries, frameworks, and IDEs. Speaking of maturity, it would be a shame not to mention that TypeScript has in fact implemented some features earlier that JavaScript did – a good example here is that of optional chaining. Additionally, TypeScript can be used not only on the frontend side: backend, along with mobile and desktop are supported as well but I’ll talk about it in greater detail in the following paragraph.

TypeScript vs JavaScript: how do the two compare?

Now that I’ve introduced you to both languages, it’s time to perform the good old “compare and contrast” analysis of what the two technologies excel at.

What makes TypeScript superior?

The fundamental difference between TypeScript and JavaScript is that the former provides static typing and type annotations. With the latter, in most cases, you simply don’t know what you’ll get – and some of the above-mentioned “WTF” examples nicely show what this situation can lead to. When you’re using TypeScript, the compiler or even IDE informs you about the existence of such a problem; when you’re writing in JavaScript, on the other hand, the issue doesn’t come to light until the tests phase. As developers, we’re not too keen on running into code-related surprises, especially when we’re involved in large-scale projects that call for predictability and readability. In this regard, TypeScript is the obvious winner of the TypeScript vs JavaScript duel.

The second major plus of TypeScript is that it supports namespaces, just like C-family languages do, and generic programming. Both of these qualities allow writing more abstract and universal code. For example, you do not have to write a function for each type. In generic way you could do something like this:

const add = <T extends {}>(x: T, y: T): T => {
return x + y;
};
const test0 = add<string>('fizz', '-buzz'); // result: 'fizz-buzz'

const test1 = add<number>(3, 7); // result: 10

In the above example, ‘T’ stands for argument type, so generic functions allow you to pass type ad-hoc, when functions are invoked and not declared.

Another noteworthy thing about TypeScript is IDE support. When object types are explicitly declared with interfaces (and function has declared argument types), WebStorm auto-completion suggests what variable you want to pass faster than you think about it.  

What’s also impressive about the JavaScript superset is that it’s essentially one language to rule them all. How come? If you write backend in TypeScript, you can share types and interfaces which is incredibly helpful when hooking front to REST API. But backend is just a beginning. We all have seen ECMAScript and its implementations spreading across all sorts of devices. Want a mobile version of your app? Perfect, React Native has great support for TypeScript. Maybe a desktop version for all platforms? No problem, Electron – also compatible with the JavaScript superset – is the go-to solution answer. Ultimately, sharing models, interfaces, or even pieces of code and whole components across your apps significantly speeds up development, leaves less space for mistakes, and is just as helpful as comprehensive documentation.

And last but not least: every programmer (at least in Merixstudio) loves to code. So why not code with the winner of the TypeScript vs JavaScript battle?

Curious what other devs think about JavaScript superset? Check out 10 reasons for use TypeScript by Barbara, our Frontend Developer.

All that glitters is not gold

Let's be honest: if something has pros, it has cons as well. TypeScript is no exception to this rule and if you’re about to use it, you should be fully aware of some disadvantages and limitations.

The first point in favor of JS in the TypeScript vs JavaScript duel is that TypeScript is still a superset of JavaScript and not its replacement. This means that developers wishing to use it simply have more to learn: plain JS features such as prototypes, generators, or async / await on the one hand and TS-specific features (which I’ve discussed above) one the other. In fact, jumping into TypeScript may be quite challenging and the first encounters with this language may be just as frustrating as switching from dynamic to static thinking.

Then, drawing from their experience with languages such as Java or C++, some programmers point to the static typing and type annotations in TypeScript being not true. This actually is a mixed blessing and, depending on your point of view, can be seen as either pros or cons. Nonetheless, it’s a fact that TypeScript provides less extensive static features than the above-mentioned languages; thus, it’s less powerful and easier to learn.

Another issue is that TypeScript does not guarantee that your program is bugless. I may be stating the obvious here, but I still believe it’s worth underlining. Are your types correct? Are you ‘null-safe’? That’s cool, but this doesn’t mean that there’s nothing wrong with your app. Maybe you’re not noticing a passing bad param, especially in the recently popular functional programming way, where variables usually have a wider scope. Or maybe something remains undefined and won’t be visible on the website. Either way, although it’s not impossible to spot bugs in TypeScript code, it is much harder – which shows in the following example which does not point to the existence of any bugs:

const someFn = (argument: any) => {...}

@ts-ignore

export interface Person {
name: string | number | boolean | undefined;
}

if (argument typeof === 'string') {...}
else if (argument typeof === 'number') {...}

const argument = probablyArgument as Argument;

As shown above, extensive use of snippets is tempting but, to be honest, it removes core TypeScript features. Sometimes it’s hard to avoid doing this but there is probably a way to do this “correctly”. The implementation of the above-mentioned scenarios could lead to a speed down of the development process, as there is a need for more time in each code review. Moreover, sometimes, trying to avoid them will consume more time than writing similar things in plain JS.

Finally, TypeScript needs more code to work than pure JavaScript, especially at the beginning of a project when all interfaces must be conceived. More code to write means more developer’s time, which then amounts to a greater cost. Another point for JS in the TypeScript vs JavaScript battle. At the same time, the more the project grows, the smaller the difference becomes, and with time, TypeScript becomes less time-consuming.

TypeScript vs JavaScript: how to migrate to the JS superset

Let’s say you already have a project written in plain JavaScript but I managed to inspire you to switch to TypeScript. Maybe you’re even considering building a mobile or a desktop version of the app. Is it possible to achieve this goal in TypeScript? And how to go about switching from JavaScript to its superset in the first place?

Answering the first question: yes, it is possible! Even though it might take some time, it’s a fairly manageable task – and you have an option to start using TypeScriptS from a certain point in the development process. All thanks to the possibility of having both .js and .ts files in your project.

Broadly speaking, we can distinguish two main stages here:

  • configuring your project to use TS,
  • gradually or instantly changing file extensions.

To give you a greater insight into the process, let me break it into more detailed steps.

Configuring a project is definitely not the easy part because the outcome depends to a large extent on what tools you’re using. In most cases, however, you start by adding some dev-dependencies to your `package.json` or just installing them globally.

Main dependency here in our case is of course TypeScript:

npm install --save-dev typescript
npm install --save-dev ts-loader // if you’re using webpack

You may or may not need some “@types” – it all depends on which library or framework you’re using at the moment. Then, move forward to the project directory and run from terminal:

tsc --init

This command will create a tsconfig.json file with basic configuration, for using both JavaScript and TypeScript, depending on the file extension. This file and all of those configuration options could be a bit overwhelming at first but it’s quite self-explanatory: there are comments to each option. As I said, it all depends on what you’re using. The most important part are those lines:

"allowJs": true,
"checkJs": false,

They will allow you to have .js (and .jsx if you’re using React) files and will not check them.

Make yourself familiar with all these options as well because that’s where TS core features come:

/* Strict Type-Checking Options */

If you aren’t using webpack, you will need to specify ‘outDir’ option in ‘compilerOption’, and explicitly tell where your source code is, e.g.

"include": ["src"]

Depending on what library/framework you are using, you should have a basic config to start using TypeScript.

Now we can proceed to the next stage which involves changing file extensions:

.js -> .ts
.jsx -> .tsx

As I said, you can do it gradually since the config lets you have JavaScript files and will not check them so it can, for example, be a part or an additional goal of a Sprint. You can do this manually or you can use some utility to batch like “linux-utils” on Linux or even plain Finder on macOS to change all your files. But be careful with that – it’s always a good idea to have your files in some VCS or at least a copy of them. With a sudden change comes the need to write interfaces anew, change all function signatures (if you’ve enabled the “noImplicitAny” option in “tsconfig.json”), and probably to modify numerous other aspects as well.

As you can see, the migration to TypeScript is rather easy but time-consuming. The bigger the project, the more time it takes to change, so splitting it into smaller parts might prove helpful.  

TypeScript vs JavaScript: key outtakes

As a developer, you’re probably used to hearing the infamous “it depends” answer to the “which one is better” questions. The question we posed today is no exception. In my opinion, JavaScript usually handles small to medium projects better than its superset. The bigger and more complex the project, the more vividly TypeScript assumes the leadership over vanilla JS. But as always, it all boils down to your needs. Sometimes it’s TypeScript that works better, sometimes it’s JavaScript.

Do you share our passion for JavaScript? Join us and let international projects fuel it daily!

Navigate the changing IT landscape

Some highlighted content that we want to draw attention to to link to our other resources. It usually contains a link .