Yet another TypeScript introduction
--
TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
The slogan on the www.typescriptlang.org website front page reveals two essential TS aspects:
- TS is a language and a compiler.
- All TS is valid JavaScript.
As the name suggests, TS is all about types, and its only purpose is making sure that your code is type safe and to achieve this goal it uses a couple of tricks.
Type inference
The most important thing you have to rely on when using TS is type inference.
The TS compiler can infer (figure out) the type of many expressions in your program without the need of any effort from your side. When that happens, it will make sure that throughout your code, any operation you make with that expression is consistent with its inferred type, even when JavaScript would allow that operation by implicitly applying some weird type coercion.
Type annotations
More often than not fellow programmers will argue that writing and adding type annotations takes time, adds overhead and even makes code less readable. Well, I will have to agree on that: more keystrokes are always worse, type annotations add noise to our codebases, and some complex type definitions are just too difficult to grasp when skim-reading our code.
Now, there is a balance between type safe and completely untyped code, and TS allows us to reach that Nirvana thanks to its powerful type inference and the expressiveness of its type system.
Minimizing annotations
Most of the time we won’t have to add type annotations to our application code, they will be provided by the libraries we use and the core of our application.
As you can see in the previous example, app-code.ts has only one type annotation HttpService<User>, but the code is 100% type safe because TS can infer the rest.
In large scale applications, it becomes even more apparent. Having a strongly typed foundation will ensure that most of our app code will automatically get enforced by the compiler.
Simplifying annotations
As a TS user, I have sometimes felt overwhelmed by the complexity of some types. TypeScript has a ton of advanced features that allow type authors to be extremely expressive, but sometimes crafting expressiveness requires sacrificing readability.
Even though type signatures can get very complicated, we always have the option of hiding that complexity by using one cool TS feature called type aliases. Type aliases are just containers for other types.
Continuing with the previous example we have added the url param to the save method, which is just a string, but we have used a more semantically correct type Url.
We have also extracted the Promise<HttpResponse<T>> annotation to another type, for the sake of readability and reusability.
Null, undefined under control
The TS compiler has some built-in tools to cope with one of the most annoying things in JS development: null and undefined.
By default null and undefined can be assigned to any type, but there’s a compiler flag --strictNullChecks that enforce you to explicitly declare that a given type can accept null or undefined.
In this example, the nullable variable uses a union type to express that it allows string and null values.
TypeScript + {your framework here}
- Angular 2: Authored in TS.
- CycleJS: Authored in TS
- React: The TS compiler supports the JSX syntax, and the React APIs are available via typings.
- Vue: Officially supported in v2.
- {your framework here}: Is your favorite framework supported? probably, search here.
IDE integration
To make the most of your TS experience, relying on a good code editor is key. For what I’ve tried so far these are my recommendations:
- Visual Studio Code (built-in support)
- WebStorm (built-in support)
I haven’t tried yet, but looks great:
- ALM tools (built-in support)
Other editors like Atom, Brackets, Sublime, etc probably have community plugins that provide good TS support.
Conclusion
- You don’t have to annotate all your expressions and declarations; type inference is your friend.
- Be expressive, use all TS tools at your disposal but be kind to your API users.
- Be explicit about null/undefined.
- If you are a framework user, it probably has TS support.
- Add TS support to your favorite IDE or just pick one with built-in support.