Nevertheless, it has the potential to change dramatically the way we design web applications. It is no surprise that this is one of the hottest topic at Codemotion Milan 2019 – tickets are still available, get yours here. If you’ll come in Milano, you should not miss the opportunity to attend Enrique Amodeo‘s talk about Typing like a Pro (with TypeScript) (more info at this link).
If you have been away from web development in the last years, coming back to it could be quite a shocking experience. Basically everything you knew has changed. Things are evolving so fast that it feels like it keeps on changing literally as you type code.
You are already know it (almost)
It is very easy to get started
Getting started with TypeScript is quite simple, especially if you are used to Node.js. The following command will install the TypeScript tools on your computer:
npm install -g typescript
Now you can start experimenting with your IDE of choice. Many tools already provide an extended support to TypeScript features. As an example, Visual Studio Code has built-in syntax-highlight, code completion and debugging utilities that will make TypeScript programming a smooth experience.
Compilation has its adavantages
As result of the compilation step, the output file hello.js will be created, ready to be interpreted by the browser or, if you have the Node run-time installed on your computer, with the following command:
Data binding is safer
The use of types in object definition allows to check at compile time if the data structure you are using fit in the code that is handling it. As an example, a number can be used in arithmetical operations, while a string is not suitable. The following code snippet show the use of types in variable definition, function arguments and return values:
While in this trivial example it is not a big deal whether you print a valid number or not, in other contexts it could be critical. Therefore, being notified of this potential issue at compile time will allow you to fix this behavior in time.
You can do OOP like a pro
The major advantage is the capability of outlining complex data models with a compact syntax that matches the expectations of developers that are familiar with OOP.
TypeScript delivers true encapsulation with access modifiers, polymorphic behavior with abstract classes and multiple inheritance through interfaces. This expressive power is unmatched even in the latest revision of the ECMAScript language, though it includes specific keywords for class definition and inheritance.
In a world where components have become the building blocks for modern web applications, this aspect of TypeScript is clearly appealing, as inheritance is one of the best ways to ensure code consistency and re-usability.
You may indeed think of web components as a way to reconcile OOP concepts with web development practices, and in this sense TypeScript comes ready to party.
Reuse code with type-safe generics
Compilation is also the enabling factor for the implementation of generics in TypeScript. Similarly to other high level languages, like C++ or Java, generic programming is a way of adapting the same piece of code to multiple data types.
Interfaces, similarly to classes, are used to define archetypal data types, but with an higher level of abstraction.
Generics and interfaces can be used together to implement type-safe template code, as shown in the following example:
In this example, the Validable interface restricts the use of the generic function validate only to instances that effectively define a method named isValid, regardless of the validation logic, that is very different for the Point and the Vehicle classes.
At the same time, the invocation of validate on objects that are not Validable will issue a compilation error. Once again, compilation prevents run-time errors on unsuitable instances and enables effective code reuse through generics.
Generics are one of those advanced features of TypeScript that you may not find needful at first. Nevertheless they allow to implement with ease a lot of design patterns that can fit in many scenarios, so they are definitely worth to understand at least in broad terms.
It has decorators that don’t decorate
Decorators are still an experimental feature of TypeScript. You have to enable the support to compilation with the following options:
tsc source.ts --target ES5 –experimentalDecorators
Decorators are applicable to classes, methods, properties and function arguments. Their name may sound a little misleading, since they are far from cosmetic, and actually apply deep changes to your code, in a meta-programming fashion.
For instance decorators are widely used in Angular for the sake of dependency injection. For the majority of developers, their use may fit in scenarios that require to address so-called cross-cutting concerns.
As the name implies, there are general requirements that apply to many parts of your business logic. User authentication for instance is a prerequisite to operations that require some level or privilege. Therefore, you may need to verify the credentials in many independent contexts. In this sense, authentication is a cross-cutting concern.
In many cases, the only option may be to implement the authentication checks in a specific function and invoke it everywhere you need it. Beside its simplicity, the major drawback of this solution is the need to actually modify working pieces of code to full-fill a non-functional requirement.
You may recognize this scenario as the perfect fit for aspect-oriented programming (AOP) and that’s exactly what decorators are meant for.
The following example gives a taste of what decorators can do in such a scenario:
A decorator is used to add authentication to the methods of a class that implement an HTTP service.
The function named authorizedOnly is attached with the decorator syntax @func_name to the methods of the dummy class MyService that need user authentication.
The body of authorizedOnly performs user authentication calling the external function isUserLoggedIn and on negative result, it injects an unnamed function in place of the decorated method that was originally invoked, showing an error message. In this example, authentication will always fail, unless you toggle the value returned by isUserLoggedIn.
No matter how complex the real business logic is, thanks to decorators it will be added to every method with a simple tag, and mostly important without modifications to the original code.
If you want to learn more on this topic, do not miss Enrique Amodeo’s talk Typing like a Pro (with TypeScript) at Codemotion Milan 2019: tickets are still available, get yours by clicking here!