The origin of TypeScript
TypeScript originated from the shortcomings of JavaScript for the development of large-scale applications both at Microsoft and among their external customers. (
https://en.wikipedia.org/wiki/TypeScript)
However, Microsoft was not the only big company searching for solutions to make JavaScript more robust at scale.
As you can see, 2010-2015 was the race to a better-typed JavaScript:
- October 2011: Google releases Dart publicly: a strong-typed language that compiles to JavaScript.
- October 2012: Microsoft publicly releases TypeScript.
- 2014: Facebook publicly releases Flow: a typed superset of JavaScript language.
- October 2014: Google announces AtScript, which would be the primary language used for Angular 2.0.
- 2015: AtScript merges with TypeScript, so do Angular 2.0
- Nowadays: React is still developed with Flow; However, TypeScript React types have existed since 2016.
What is TypeScript
TypeScript is a language that we can describe as:
A static structural typing (with erasure) language targeting JavaScript
Let's decompose this sentence:
Static typing (...) with erasure
TypeScript provides a static typing system, meaning that once compiled, the generated code does not contain any type annotations or assertions.
This point is essential, TypeScript does not guarantee that the behavior at runtime will match the type declarations.
Since JavaScript is still dynamically typed, leaving some comments about types in the code would be pointless for V8 or other engines that have their owns optimization systems.
However, we will see - in Chapter 4 - that there are many TypeScript architectural strategies applicable to tighten this "runtime gap."
Structural typing
Unlike Java or other strongly typed languages, the TypeScript typing system is structural.
This means that TypeScript matches types by looking at their shape, not simply on their names.
Let's see a simple example with the interface keyword used to type JavaScript objects (and more, see Chapter 2):
1// A Person has a mandatory `name` property of type `string`
2interface Person {
3 name: string
4}
5
6// An Animal has a mandatory `name` property of type `string`
7interface Animal {
8 name: string
9}
10
11function doSomethingWithPerson(p: Person) {
12 // ...
13}
14
15let a: Animal = { name: 'cat' };
16
17doSomethingWithPerson(a) // valid is TypeScript, impossible in C#/Java
18
Targeting JavaScript
We will often talk about the TypeScript compiler; However, TypeScript is a transpiler, a superset of JavaScript, that produces valid JavaScript code.
On top of its type system, TypeScript, similarly to Babel, also provides access to a range of ES next features such as top-level
await or the
Nullish coalescing operator (
??).
The good reasons to use TypeScript
TypeScript is a superset of JavaScript - and will always be
Learning TypeScript comes with two good news:
-
You are already familiar with TypeScript
TypeScript design aims to stay as much as possible aligned with JavaScript's upcoming standards.
If you are familiar with JavaScript, you will see that learning the basics of TypeScript is very intuitive.
-
Learning TypeScript is learning the future of JavaScript (with types)
Unlike Dart or Babel, TypeScript gives us early access to features that will be standardized - for sure - in ECMAScript (late stages).
It means that, typings aside, all the JavaScript syntax that you will learn is also reusable knowledge for a non-TypeScript project such as working on a modern Node.js backend implementation.
No more typos
As we will see in the upcoming chapters, TypeScript is very good at inferring types from untyped or partially typed code (we will see in Chapters 3 & 4 how to type most of it), especially typos, from mistyped variables to wrong function arguments.
TypeScript will take care of the checking the validity of the code.
When configured and used correctly (we will see in Chapters 3 & 4 how to type most of it), some studies show that the type use results in a 15% decrease in bugs.
The 15% bug reduction essentially represents the "low hanging fruits" part of bugs resulting from typos or JavaScript dynamic typing issues.
More time to focus on your code
As seen in the previous page, working on modern plain JavaScript projects requires a lot of memory to keep the application's context (functions, components) and dependencies in mind.
Nowadays, almost all popular JavaScript libraries and frameworks are released with TypeScript types, make the discovery of its features seamless.
Let's see what React typings brings:
Easily find the hooks provided by React's core.
useState() can take any value or a initializer function, did you know that? 👀
TypeScript has full support for React components (see Chapter 2)
TypeScript will reduce the mental load required to work on modern front-end (large) projects, allowing you to spend more time focusing on your work.
Grow your projects with confidence
Working as a team using TypeScript can be seen as having "contracts" between components, part of the application, team-mates.
Since any breaking change will raise some TypeScript errors, TypeScript will help you make changes in a backward-compatible way or, at least, notice when you broke its usage.
Other key benefits of TypeScript are its refactoring features shipped with VSCode.
Thanks to the VSCode Integration with the TypeScript typing system, refactoring such as renaming, moving, extracting code is much easier.
Renaming this React component props type will also change it into all files using it
The wrong reasons to use TypeScript
TypeScript makes my code error-prone, no need for tests
As we saw in the "What is TypeScript?" section, the JavaScript code generated by TypeScript's compiler does not contain any type runtime type assertions.
The strength of your TypeScript types relies on your usage of TypeScript.
For this reason, we will cover in Chapter 4 the best approaches to strengthen your JavaScript application by leveraging good TypeScript architectural patterns.
Finally, even in a strongly-typed language like Java, types cannot guarantee that the logic applied to the data will match some functional requirement (specs).
Types alone are not sufficient for stability; Only testing strategies can help reach true assertion of a product's good functioning.
TypeScript is magic
TypeScript being pretty smart, even with untyped code, might lead to think that TypeScript is a magical tool in every developer journey.
It is true that, with minimal effort, TypeScript can already bring a lot of advantages on the developer experience side: infer types from usage, autocompletion/navigation, dead code warnings.
However, improving codebase stability by leveraging TypeScript requires a real investment:
- When it comes to legacy projects, the migration to a more stable product by leveraging TypeScript will be a multiple-phases migration project (see Chapter 4)
- When it comes to reusable code use-case (data helpers, functions composition, UI-Kit components), the required types require excellent knowledge of advanced TypeScript types.
- Scaling a project using TypeScript requires properly factorize types to avoid duplication; Real architecture work is recommended.
- Finally, the TypeScript compilation time is likely to increase over time. While some well-known solutions exist, they can require some not insignificant work on a codebase with a complex build configuration.
Using TypeScript on a large-scale or legacy projects is not a low-hanging fruit solution. It's an investment.