Before Migrating to TypeScript

Aug 12, 2020 • ☕️ 6 min read

The debate whether to use TypeScript is over, as library maintainers you should (or even must) support typings, as app developers you can get away in personal projects but often required in enterprises.

Honestly I don’t like TypeScript because its typing system is nothing compare to my previous experience with static strongly-typed languages like Java and Swift.

But I do learn and use TypeScript daily!

I want to think JavaScript/TypeScript combination like C/C++. In 2020, people expect you to know JavaScript slash TypeScript not just only vanilla JavaScript. You’ll see that more often in frontend job descriptions.

I’m not trying to convince you to switch but only here to help people already decided and still early in migration.

This post is a curated list of heads-up for you to migrate to TypeScript smoothly with minimum effort. The point to get the right expectation not to get intimidated by its drawbacks.

Static typing matters more in team

I often use vanilla JavaScript in indie personal projects because it’s compact and efficient. I know what I’m doing with many assumptions in my head and of course no documentation or testing at all, I don’t even need fancy intellisense.

If I’m writing applications with a team of people, maintained over many years by different people and I would like some confidence that the code is at least logically sound in terms of the data types being passed around.

Typescript provides typing, latest ECMAScript features and great tooling support with intellisense. All these features together make project self documented and tested in some degree, so that other developers can go through it easily with confidence.

Way more complicated than expected

TypeScript is not there to support JavaScript, it’s a new programming language!

Even you are advertised that TypeScript is just JavaScript with types, follows ECMAScript specification closely, and compiled to JavaScript but in the end it’s way more complicated than that with its own rules, types, declarations, utilities and ecosystem.

To take full advantages of TypeScript you must use it almost everywhere or not using at all. Using TypeScript in frontend frameworks is quite stressful honestly and it has a steep learning curve to work fluently in big projects even though you are already a veteran JavaScript developer.

The migration has to be gradual

Play with your codebase and try out various approaches before committing to one of them. Sometimes finishing the migration quickly may take priority. Sometimes the code remaining fully functional during the migration may take priority.

While it might feel somewhat overwhelming, the long-term gains become apparent much more quickly.

It’s not unexpected to get error messages after conversion. The important thing is to actually go one by one through these and decide how to deal with the errors

TypeScript comes with certain checks to give you more safety and analysis of your program. Once you’ve converted your codebase to TypeScript, you can start enabling these checks for greater safety

Full typing coverage obsession is real

JavaScript is an incredibly dynamic language. You can modify any object at any time, call functions with a different number of arguments than they expect, randomly flatten objects together, and so much more. Trying to perfectly capture that dynamic behavior in static types is almost impossible.

Note that I’m not saying I’m against having 100% type coverage. It’s just that, like unit test coverage, getting that last 10-20% becomes much much harder, and it doesn’t seem like the benefits are necessarily worth the amount of time you have to put in to make it happen.

Don’t feel like you have to use TS for every single thing!

Don’t let “perfect typing” to become the enemy of “good functionality”.

Many libraries don’t have typings

TypeScript works best when all of your project dependencies have typings and that’s obviously not the case currently.

Of course you love those libraries ship with typings (written in TypeScript or just including TypeScript declaration files), these will be working flawlessly with one caveat that documentation and sample codes might be only available for JavaScript.

Many libraries don’t ship with typings but having type declarations in DefinitelyTyped, these work just fine but sometimes type declaration package versions and library package versions get out of sync. Unpopular libraries often left in dust and way behind the original ones.

The worst case is not having typings anywhere, you can fix it by writing your own declarations for it. And I can tell you that you will not like it!

If you had previous experience with typed languages then you will concluded that TypeScript is just a flaw and created a false impression of type safety! Its safety is not completed and it’s not really safe at runtime.

It’s not really safe at runtime

Static typings work best when you consume a libraries shipped with type declarations in a TypeScript project.

But don’t forget that it only guarantees type safety at compile time. You need data validation to achieve safety at runtime.

Do you write tests for every possible combination of input data types to your functions? Or do you assume it’s only called with the “right” inputs? Don’t forget that consumers are not guaranteed to use TypeScript.

I don’t think that TypeScript replaces tests, but it should give you a baseline level of safety and lessen the need for a lot of things you would have written unit tests for otherwise.

Be really careful with any, void, null, undefined, never. Those types caused me a lot of headaches when consuming in JavaScript projects.

This is the reason why I called TypeScript is a flaw compares to other strongly-typed languages like Java or Swift. All TypeScript declarations will be striped off after compilation and sometimes I don’t trust the compiled JavaScript when it might not work as expected.

This explains very well why TypeScript has steep learning curve because you not only learn how to use it but also need to know how it will compiled to JavaScript. It’s all JavaScript at runtime in any host environments!

TypeScript does not come with built in polyfills, remember to set in config file.

Documentation and sample codes often written for JavaScript

This is really a big big problem with libraries not originally written in TypeScript, especially those SDKs from giants with hundreds of APIs. This is a nightmare!

Some libraries written in JavaScript with dynamic APIs, you just don’t know how to type those APIs properly in TypeScript. Even worse it’s the only available solution :v

I find myself looking at original codes quite often to know how to consume APIs in TypeScript. TypeScript needs many overload functions to cover one dynamic JavaScript function and that will confuse you if no documentation available!

There is no going back

I just want to emphasize that TypeScript is a new language not a tool to support JavaScript. There is no going back after putting a lot of effort to migrate a big project to TypeScript. You are moving into a new language and its ecosystem.

Plan your migration carefully before making a move:

  • Do important dependencies have typings?
  • Do your team have experience with typed languages?
  • Will you migrate all at once or gradually?
  • Will it be better to completely rewrite in TypeScript than migrating?

Where to go from here

Overall, I think that TS should be used in any meaningfully-sized app that will be maintained long-term, or worked on by multiple people. But, at the same time, TypeScript is a tool, with strengths, weaknesses, and tradeoffs. Take time to understand those tradeoffs and whether they are a benefit for you, and use it wisely.

As your application grows, you may find it helpful to include a type system to assist in development. Just choose the right tool for the task at hand, and create something great with it.

Too bad! Same old story! Once you’ve finished building your house you notice you’ve accidentally learned something that you really should have known—before you started. (Friedrich Nietzsche, Beyond Good and Evil)

Further reading:

Related Articles

Bull - queue system for handling distributed jobs and messages in Node

Bull is the fastest, most reliable, Redis-based queue for Node. I have been using it for years to handle async jobs and schedule messages

Binaryen - WebAssembly Compiler and Toolchain

An overview of Binaryen as compiler infrastructure and toolchain library for WebAssembly in written C++

Beloved CSS Frameworks

Pros and cons of using CSS frameworks like Bootstrap, Foundation, Materialize CSS, Semantic UI, Tailwind, Ant Design

WebAssembly - The next Big Thing in Tech

An overview of what WebAssembly (Wasm) is, how it works, and it's current position in the web development stack