Sitemap
sprang

Spring, Angular and Architecture

TypeScript for Java developers: Common pitfalls

--

I have been a Java programmer for more than a decade, using the Java language daily. When I started to write frontend code, I felt much more at ease with TypeScript than with JavaScript alone because it is more similar to Java. However, there are fundamental differences between the two languages. This blog post will point out common pitfalls encountered when starting with TypeScript and provide guidance for writing high-quality TypeScript code.

A class might not be a class

TypeScript classes are great for solving complex business problems in an object-oriented (OO) manner. In client-side applications, data often comes from a backend service as a JSON payload, which can be transformed into an interface type in TypeScript. However, I have noticed a common mistake where a class is used instead of an interface type. As an experienced OO programmer, I tend to implement functions that operate on the properties of the interface type within a class. However, this approach does not work since, during runtime, only a JSON object is available, which does not have the added functionality of the class.

When adding the function getValueOrDefault(), the example still transpiles, but fails at runtime.

Function references are great, but…

One neat feature of Typescript is keeping the this keyword inside class functions. With Javascript only, this would be the caller’s context instead of the class instance.

Once knowing this feature, you start using Typescript’s arrow functions everywhere. But most Typescript beginners I met do not use arrow functions when creating function references. Instead they return the reference as this.myFunction. In order to keep the this within the function here as well, you have to use the arrow function again: () => this.myFunction().

Function references without using the arrow function have serious impacts.

Enums vs. types

In Javascript, there is no concept of enums, and Typescript enums are just an abstraction of runtime values. Per default, an enum’s value is a number, given by the order of the enum value declarations. Thus, changing the order of the enum values will lead to inconsistencies with previous stored data, and matching an enum value’s name with a JSON string will fail. Both problems can be solved by setting explicit values for enums.

Another solution is using types of string constants. Such a type is like a string, but any value not matching the defined constants, leads to transpiler errors.

It is a good practice to always set the enum options to concrete values.

To better understand Typescript enums, I recommend checking out a simple example’s transpiled Javascript output.

instanceof and type casting

instanceof is another keyword that exists both in Java and TypeScript/JavaScript. But again, the runtime result cannot be determined solely by the TypeScript type. Instead, instanceof will compare the two classes’ constructors at runtime.

Similarly type casting can be confusing and different dependent on the Typescript version. When you cannot cast from one type to another, but you have to for whatever reason, you can always cast to any and then back to the new type you need.

The difference of Javascript’s runtime instanceof keyword and the Typescript transpile-time types.

!myString

The last code snippet is pretty self-explanatory and shows that an empty String is interpreted as false in conditions.

Summary

Starting with Typescript before knowing Javascript well can be tough. It is important to know what language features are just syntactic sugar and what really happens in runtime. A successful transpilation does not guarantee that there will not be any runtime issues, as some issues may only arise during runtime and not in the compiled code.

--

--

Responses (1)