Written by Dmitri Gabbasov
In this post we are going to explore the reasons why we have chosen TypeScript as our main development language at Sixfold and why we are happy with it.
The ECMAScript standard, first published in 1997, reached its 5th edition in 2009. The development of this edition took a long time and involved disputes between the two major contributors — Netscape and Microsoft.
Throughout the process, features like classes, modules and even static typing were already discussed, however, none of them actually made it into ES5. If you are interested in the history of ECMAScript then I suggest you read this paper by Brendan Eich and Allen Wirfs-Brock.
Since 2015, the ECMAScript standard has continuously evolved, releasing a new edition every year. Similarly, other web-related technologies and standards were also evolving rapidly. Various APIs were being added that gave web pages more and more power (e.g.
<video>, History, Storage, File and Blob, Crypto, WebRTC).
Lastly, Node.js was released in 2009, eventually becoming a popular server-side stack choice.
Also, here is some reasoning provided by Anders Hejlsberg — one of the creators of TypeScript — back when TypeScript was released in 2012:
What we like about it
Why Node.js? Well, that question warrants an entire blog post of its own. Maybe we’ll write about that in the future. For now, here are some of the key things that our engineers like about TypeScript.
TypeScript is well integrated into the major IDEs. There’s good support for navigation and refactoring provided by the compiler toolchain itself, and some IDEs, like WebStorm, build further on top of that to support even more advanced use cases.
Actually, the fact that TypeScript ships with a language-server-like module, which allows clients to query information about symbols and perform refactorings by sending messages over a TCP socket, has probably made it easier for various IDEs and text editors to so quickly provide full-fledged support for the language. Compare this with older languages where an IDE would need to essentially reimplement the compiler for every language it wants to support.
The available type information also makes it easier to explore new APIs, as well as use familiar ones, by way of showing auto-complete and parameter information popups.
It is a well known idea, that the earlier a bug is discovered, the cheaper it is to fix it. Being able to detect errors during compilation, or right inside your IDE as you type, can therefore help avoid many costly mistakes.
TypeScript allows one to introduce types gradually, so to speak. It is fine to leave out type annotations when development speed is important and you only need to prototype something. You can later add more type information to your code and make things as strict as necessary. Similarly, not all your dependencies need to supply type information, you can still use them even if they don’t, although without the benefits that types bring.
Having type annotations present in certain places makes the code more readable. Type inference also helps a lot here, as you don’t need to litter your code with types. Mostly, you only need to put them in specific relevant places, like field and function declarations.
Many third-party libraries already ship with type information. Those that don’t, very likely have type definitions created by the community as part of the wonderful DefinitelyTyped project.
TypeScript has good documentation and due to its popularity also has great community resources available.
Big company backing
TypeScript’s development is backed by a large organization (Microsoft), which is an important fact when choosing a technology to run your business and assessing its longevity. At the same time, the team’s development process is very much open to the community. Even the their meeting notes are available in GitHub for everyone to read.
What makes it harder to like
We also asked what our engineers think are some of the shortcomings of TypeScript. Following three things stood out. Note that they are not necessarily bad things, but rather can present obstacles to some people in certain situations.
??) and the optional chaining (
?.) operators. The latter in particular had been a requested feature in TypeScript since 2014, but was not implemented until November 2019, after it had become a stage 3 proposal in TC39. The proposal was then accepted into ES2020.
Advanced type system
For people coming from languages like Java or C#, TypeScript’s type system might be somewhat surprising at first. The big difference here is that TypeScript has a structural type system, as opposed to a nominal one. Two types with different names (or even without a name) can still be considered to be the same type, if they have the same structure. This is not the case in many other languages.
Also, TypeScript’s type system is quite advanced and allows to do various “tricks” that are not possible elsewhere. For example, union types make it possible for a property or variable to have multiple types, which can be discerned, if necessary, via various operations. Mapped types allow transforming one type into a different looking one, by applying certain transformations to it. All this can initially stump developers who have worked with other languages in the past.
No real programming language has a type system that is 100% sound. Having such a property would mean that any valid program in that language is guaranteed to never throw an unexpected error or crash. However, some languages are better than others at isolating areas of code that can misbehave from code that can not. Being more sound usually comes at the expense of having to write more verbose code.
Since the beginning TypeScript has tried to strike a good balance in this matter — being as sound as possible, without forcing users to write complex code. In fact, soundness in TypeScript is highly configurable through various “strictness” flags, which turn certain language features on or off. Ideally, one would write TypeScript code with maximum strictness turned on, which we also do here at Sixfold.
A few times however, we have encountered errors at runtime, that we wish were preventable at the type level. These issues typically have something to do with the more “forgiving” aspects of the type checker, such as indexed property accessor types (think
someArray[i] not including
undefined in its type), and the lack of distinction between optional properties and required properties with
undefined in their type.
Ultimately, we can’t quite imagine writing Node.js or front-end code in anything other than TypeScript. It is really a no-brainer at this point. Even if you don’t want to be concerned with declaring your own types, you could at least make use of the type definitions of other libraries and built-in objects, it is still beneficial.