TypeScript enums

This blog is a part of my TypeScript series, and the previous ones are:

1. Why program in TypeScript
2. Structural vs nominal typing
3. Getting started with TypeScript classes
4. Access modifiers public, private, and protected
5. Abstract classes

Enumerations (a.k.a. enums) allow you to create limited sets of named constants that have something in common. For example, a week has seven days, and you can assign numbers from 1 to 7 to represent them. But what’s the first day of the week?

According to the standard ISO 8601, Monday is the first day of the week, which doesn’t stop such countries as USA, Canada, and Australia consider Sunday as the first day of the week. Hence using just numbers from 1 to 7 for representing days may not be a good idea. Also, what if someone will assign the number 8 to the variable that store the day? We don’t want this to happen and using day names instead of the numbers makes our code more readable.

On the other hand, using numbers for storing days is more efficient than their names. So we want to have readability, the ability to restrict values to a limited set, and efficiency in storing data. This is where enums can help.

TypeScript has the enum keyword that can define a limited set of constants, and we can declare the new type for weekdays as follows:

enum Weekdays {
  Monday = 1,
  Tuesday = 2,
  Wednesday = 3,
  Thursday = 4,
  Friday = 5,
  Saturday = 6,
  Sunday = 7
}

Here, we define a new type Weekdays that has a limited number of values. We initialized each enum member with a numeric value, and a day of the week can be referred using the dot notation:

let dayOff = Weekdays.Tuesday;

The value of the variable dayOff is 2, but if you’d be typing the above line in your IDE or in TypeScript Playground, you’d be prompted with the possible values as shown on the next screenshot.

Using the members of the enum Weekdays stops you from making a mistake and assigning a wrong value (e.g. 8) to the variable dayOff. Well, strictly speaking, nothing stops you from ignoring this enum and write dayOff = 8 but this would be a misdemeanor.

We could initialize only Monday with 1, and the rest of the days values will be assigned using auto-increment, e.g. Tuesday will be initialized with 2, Wednesday with 3 and so on.

enum Weekdays {
  Monday = 1,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

By default, enums are zero-based, and if we wouldn’t initialize the Monday member with one, its value would be zero.

Reversing numeric enums

If you know the value of the numeric enum, you can find the name of the corresponding enum member. For example, you may have a function that returns the weekday number and you’d like to print its name. By using this value as an index, you can retrieve the name of the day.

enum Weekdays {  // Declaring a numeric enum
  Monday = 1,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

const getDay = () => 3;  // A function that returns 3
const today = getDay();  // today is equal 3

console.log(Weekdays[today]);  // Getting the name on the member that’s equal to 3 

In the last line, we retrieve the name of the day, and it’ll print Wednesday on the console.

In some cases, you don’t even care which numeric values are assigned to the enum members, and the following function convertTemperature() illustrates this. It converts the temperature from Fahrenheit to Celsius or visa versa. In this version of convertTemperature(), we won’t use enums, but then will re-write it with them. This function takes two parameters: temperature and conversion direction

function convertTemperature(temp: number, fromTo: string): number { 

  return ('FtoC' === fromTo) ?
      (temp - 32) * 5.0/9.0:  // Convert from Fahrenheit to Celsius
      temp * 9.0 / 5.0 + 32;  //Convert from Celsius to Fahrenheit
}

console.log(`70F is ${convertTemperature(70, 'FtoC')}C`);  
console.log(`21C is ${convertTemperature(21, 'CtoF')}F`);  
console.log(`35C is ${convertTemperature(35, 'ABCD')}F`);  

This function converts the value from Celsius to Fahrenheit if you pass any value as a fromTo parameter except FtoC. In the last line, we purposely provided the erroneous value ABCD as a fromTo parameter, and this function still converts the temperature from Celsius to Fahrenheit. The attempts to invoke a function with the erroneous values should be caught by the compiler and this is what TypeScript enums are for. You can see it in action here.

In the next listing, we declare the enum Direction that restricts the allowed constants to either FtoC or CtoF and nothing else. We also changed the type of the fromTo parameter from a string to Direction.

enum Direction {  // Declaring the enum Direction 
  FtoC,
  CtoF
}

function convertTemperature(temp: number, fromTo: Direction): number {  

      return (Direction.FtoC === fromTo) ?
             (temp - 32) * 5.0/9.0:
             temp * 9.0 / 5.0 + 32;
}

console.log(`70F is ${convertTemperature(70, Direction.FtoC)}C`); 
console.log(`21C is ${convertTemperature(21, Direction.CtoF)}F`); 

Since the type of the second parameter of the function is Direction, we have to invoke this function providing one of this enum’s member, e.g. Direction.CtoF. We’re not interested in what is the numeric value of this member. The purpose of this enum is just to provide a limited set of constants: CtoF and FtoC. The IDE will prompt you with two possible values for the second parameter, and you won’t make a mistake providing a random value.

Enum members are initialized with values (either explicitly or implicitly). All examples included in this section had enum members initialized with numbers, but TypeScript allows you to create enums with string values, and we’ll see such examples next.

String enums

In some cases, you may want to declare a limited set of string constants, and you can use string enums for this, i.e. enums that have their members initialized with string values. Say you’re programming a computer game where the player can move in the following directions:

enum Direction {
    Up = "UP",       
    Down = "DOWN",   
    Left = "LEFT",   
    Right = "RIGHT", 
}

When you declare a string enum, you must initialize each member. You may ask, “Why not just use a numeric enum here so TypeScript would automatically initialize its members with any numbers?” The reason is that in some cases you want to give meaningful values to the enum members. For example, you need to debug the program and instead of seeing that the last move was 0, you’ll see that the last move was UP.

And the next question you may ask, “Why declare the enum Direction if I can just declare four string constants with the values UP, DOWN, LEFT, and RIGHT?” You can, but let’s say we have a function with the following signature:

move(where: string)

A developer can make a mistake (or a typo) and invoke this function as move(“North”). But North is not a valid direction, and it’s safer to declare this function using the enum Direction:

move(where: Direction)

As you see, wrong argument value is caught by the compiler (1), and auto-complete (2) prevents mistakes

We made a mistake and provided a string “North” in line 15, and the compile-time error would read “Argument of type ‘”North”‘ is not assignable to the parameter of type ‘Direction’.” In line 20, the IDE offers you a selection of valid enum members so there’s no way you provide the wrong argument.

Now, let’s imagine that you need to keep track of the app state changes. The user can initiate a limited number of actions in each of the views of your app. Say, you want to log the actions taken in the view Products. Initially, the app tries to load products, and this action can either succeed or fail. The user can also search for products. To represent the states of the view Products you may declare a string enum as follows:

enum ProductsActionTypes {
  Search = 'Products Search', 
  Load = 'Products Load All', 
  LoadFailure = 'Products Load All Failure', 
  LoadSuccess = 'Products Load All Success' 
}

// If the function that loads products fails...
console.log(ProductsActionTypes.LoadFailure);  

When the user clicks on the button to load products, you can log the value of the member ProductsActionTypes.Load, which will log the text ‘Products Load All’. If the products were loaded successfully, log the value of ProductsActionTypes.LoadFailure, which will log the text ‘Products Load All Failure’.

Note: Some state management frameworks (e.g. Redux) require the app to emit actions when the app state changes. If we’d declare a string enum like in the above listing, we’d be emitting actions ProductsActionTypes.Load, ProductsActionTypes.LoadSuccess et al.

Note: String enums are not reversible, and you can’t find the member’s name if you know its value.

const enums

If you use the keyword const while declaring enum, its values will be inlined and no JavaScript will be generated. Let’s compare the generated JavaScript of enum vs const enum. The left side of the following screenshot shows the enum declared without the const, and the right side shows the generated JavaScript. For illustration purposes, in the last line, we just print the next move.

Now let’s just add the keyword const on the first line before the enum, and compare the generated JavaScript (on the right) with the one from the screenshot above.

As you see, the JavaScript code for the enum Direction was not generated – it was erased. But the values of the enum member that was actually used in the code (i.e. Direction.Down) was inlined in JavaScript.

Using const with enum results in more concise JavaScript, but keep in mind that since there is no JavaScript code that would represent your enum, you may run into some limitations, e.g. you won’t be able to reverse the numeric enum member name by its value.

Overall, with enums, the readability of your programs increases. Besides, using enum is the step in the right direction: moving away from the type any.

If you like this blog series, consider reading our book “TypeScript Quickly”. So far, only 175 pages are available, but the publisher will be releasing the new content monthly.
An extra bonus: this book will not only introduce you to TypeScript programming, but you’ll also learn how the blockchain technology works while going over multiple sample apps.

Advertisements

Abstract classes in TypeScript

This blog is a part of my TypeScript series, and the previous ones are:

1. Why program in TypeScript
2. Structural vs nominal typing
3. Getting started with TypeScript classes
4. Access modifiers public, private, and protected

If you add the abstract keyword to the class declaration, it can’t be instantiated. An abstract class may include methods that are implemented as well as the abstract ones that are only declared.

And why would you even want to create a class that can’t be instantiated? The reason is that you may want to include some non-implemented methods in a class, but you want to make sure that these methods will be implemented in its subclasses. This concept is easier to grasp while working on a specific task, so let’s consider a coding assignment and see how abstract classes can be used there.

An assignment with abstract classes

A company has employees and contractors. Design the classes to represent workers of this company. Any worker’s object should support the following methods:

constructor(name: string)

changeAddress(newAddress: string)

giveDayOff()

promote(percent: number)

increasePay(percent: number)

In our scenario, to promote means giving one day off and raising the salary by the specified percent. The method increasePay() should raise the yearly salary for employees but increase the hourly rate for contractors. How do you implement methods is irrelevant; a method can just have one console.log() statement.

Let’s work on this assignment. We’ll need to create the classes Employee and Contractor, which should have some common functionality. For example, changing the address and giving a day off should work the same way for contractors and employees, but increasing pay requires different implementation for these categories of workers.

Here’s the plan: we’ll create the abstract class Person with two descendants: Employee and Contractor. The class Person will implement methods changeAddress(), giveDayOff(), and promote(). This class will also include a declaration of the abstract method increasePay(), which will be implemented (differently!) in the subclasses of Person shown next.

abstract class Person {  // 1

constructor(public name: string) { };

changeAddress(newAddress: string ) {  // 2
   console.log(`Changing address to ${newAddress}`);
}

giveDayOff() {  // 2
console.log(`Giving a day off to ${this.name}`);
}

promote(percent: number) {  // 2
   this.giveDayOff();
   this.increasePay(percent);  // 3
}

abstract increasePay(percent: number);  // 4

}

1. Declaring an abstract class
2. Declaring and implementing a method
3. “Invoking” the abstract method
4. Declaring an abstract method

If you don’t want to allow invoking the method giveDayOff() from external scripts, add private to its declaration. If you want to allow invoking giveDayOff() only from the class Person and its descendants, male this method protected.

Note that you are allowed to write a statement that “invokes” the abstract method. Since the class is abstract, it can’t be instantiated, and there is no way that the abstract (unimplemented method) will be actually invoked. If you want to create a descendant of the abstract class that can be instantiated, you must implement all abstract methods of the ancestor. The code in the next listing shows how we implemented the classes Employee and Constructor.

class Employee extends Person {

  increasePay(percent: number) {
    console.log(`Increasing the salary of ${this.name} by ${percent}%`);  // 1
  }
}

class Contractor extends Person {
  increasePay(percent: number) {
    console.log(`Increasing the hourly rate of ${this.name} by ${percent}%`);  // 2
  }
}

1. Implementing the method increasePay() for employees
2. Implementing the method increasePay() for contractors

The next listing shows how can we see our solution in action. We’ll create an array of workers with one employee and one contractor and then iterate through this array invoking the method promote() on each object.

const workers: Person[] = [];  // 1

workers[0] = new Employee('John');
workers[1] = new Contractor('Mary');

workers.forEach(worker => worker.promote(5));  // 2

1. Declaring an array of the superclass type
2. Invoking promote() on each object

The workers array is of type Person, which allows us to store there the instances of descendant objects as well.

Since the descendants of Person don’t declare their own constructors, the constructor of the ancestor will be invoked automatically when we instantiate Employee and Contractor. If any of the descendants declared its own constructor, we’d have to use super() to ensure that the constructor of the Person is invoked.

You can run this code sample in the TypeScript playground, and the browser console will show the following output:

Giving a day off to John
Increasing the salary of John by 5%
Giving a day off to Mary
Increasing the hourly rate of Mary by 5%

The previous code fragment gives an impression that we iterate through the objects of type Person invoking Person.promote(). But realistically, some of the objects can be of type Employee while others are instances of Contractor. The actual type of the object is evaluated only during runtime, which explains why the correct implementation of the increasePay() is invoked on each object. This is an example of polymorphism – a feature that each object-oriented language supports.

Protected constructors

In the previous blog, we declared a private constructor to create a singleton. There’s some use for protected constructors as well. Say you need to declare a class that can’t be instantiated, but its subclasses can. Then, you could declare a protected constructor in the superclass and invoke it using the method super() from the subclass constructor.

This mimics one of the features of abstract classes. But a class with protected constructor wouldn’t let you declare abstract methods unless the class itself is declared as abstract.

TypeScript access modifiers public, private, protected

This blog is a part of my TypeScript series, and the previous ones are:

1. Why program in TypeScript
2. Structural vs nominal typing
3. Getting started with TypeScript classes

TypeScript includes the keywords public, protected, and private to control access to the members of a class i.e. properties or methods.

Class members marked public can be accessed from the internal class methods as well as from the external scripts. This is a default access.

Class members marked as protected can be accessed either from the internal class methods or from its descendants.

The private class members can be accessed from within the class only.

NOTE: If you know languages like Java or C#, you may already know the concept of restricting the access level with private and protected keywords. But TypeScript is a superset of JavaScript, which doesn’t support the private keyword, so the keywords private and protected (as well as public) are removed during the code compilation. The resulting JavaScript won’t include these keywords and you can consider them just as a convenience during development.

The next screenshot illustrates the protected and private access level modifiers. In line 15, the code can access the protected ancestor’s method sayHello(), because its done from the descendant. But when we clicked Ctrl-Space after this. In line 21, the variable age is not shown in the auto–complete list because it’s declared as private and can be accessed only within the class Person.

This code sample shows that the subclass can’t access the private member of the superclass. In general, only a method from the class Person can access private members from this class.

To try this code on your own, visit the TypeScript playground here.

While protected class members are accessible from the descendant’s code, they are not accessible on the class instance. For example, the following code won’t compile and will give you the error “Property ‘sayHello’ is protected and only accessible within class ‘Person’ and its subclasses”:

const empl = new Employee(); +
empl.sayHello(); // error

DISCLAMER: IMO, the protected access level is useless in any programming language. I explained why they are useless in Java back in 2006. Then I continued my witch hunt against seemengly protected creatures in the Adobe Flex framework. As I’m getting older, my motivation to fight protected variables is not as strong as it used to be. Live and let live.

Let’s look at another example of the class Person, which has a constructor, two public and one private property. First, we’ll write a long version of the class declaration.

class Person {
    public firstName: string;
    public lastName: string;
    private age: number;

    constructor(firstName:string, lastName: string, age: number) {
        this.firstName = firstName;
        this.lastName;
        this.age = age;
    }
}

The constructor in the class Person performs a tedious job of assigning the values from its argument to the respective members of this class. By using access qualifiers with the constructor’s arguments, you instruct the TypeScript compiler to create class properties having the same names as constructor’s arguments. The compiler will auto-generate the JavaScript code to assign the values given to the constructor to class properties. This will make the code of the TypeScript class more concise as shown in the next screenshot.

TIP: If you’d use just the readonly qualifier with constructor arguments, TypeScript compiler would also create read-only class variables for them.

In line 8, I create an instance of the class Person passing the initial property values to its constructor, which will assign these values to the respective object’s properties. In line 10, I wanted to print the values of the object’s properties firstName and age, but the latter is marked with a red squiggly line. If you hover the mouse over the erroneous fragment, you’ll see that the TypeScript’s static analyzer (it runs even before the compiler) properly reports an error:

Property age is private and only accessible within class Person.

In the TypeScript playground, the JavaScript code is generated anyway because from the JavaScript perspective, the code in line 10 is perfectly fine. But in your projects, you should always use the compiler’s option noEmitOnError to prevent the generation of JavaScript until all TypeScript syntax errors are fixed.

Implementing a singleton with a private constructor

Imagine, you need to create a single place that serves as a storage of important data in memory representing the current state of the app. Various scripts can have an access to this storage but you want to make sure that only one such object can be created for the entire app, also known as a single source of truth.

Singleton is a popular design pattern that restricts the instantiation of a class to only one object. How do you create a class that you can instantiate only once? It’s a rather trivial task in any object-oriented language that supports the private access qualifier.

Basically, you need to write a class that won’t allow using the new keyword, because with the new, you can create as many instances as you want. The idea is simple – if a class has a private constructor, the operator new will fail.

Then, how to create even a single instance of the class? The thing is that if the class constructor is private, you can access if only within the class, and as the author of this class, you’ll responsibly create it only once by invoking that same new operator from the class method.

But can you invoke a method on a class that was not instantiated? Of course, you can! JavaScript (as well as its big brother TypeScript) support static class members, which are shared between multiple instances of the class.

The next listing shows our implementation of the singleton design pattern in a class AppState, which has the property counter. Let’s assume that the counter represents our app state, which may be updated from multiple scripts in the app.

Any of such scripts must update the only place that stores the value of the counter, which is the singleton instance of AppState. Any script that needs to know the latest value of the counter will also get it from the AppState instance.

The class AppState has a private constructor, which means that no other script can instantiate it using the statement new. It’s perfectly fine to invoke such a constructor from within the AppState class, and we do this in the static method getInstance().

The method getInstance() is static, and this is the only way we can invoke a method in the absence of the class instance.

class AppState {

    counter = 0;  
    private static instanceRef: AppState;

    private constructor() { }

    static getInstance(): AppState {
        if (AppState.instanceRef === undefined) {
            AppState.instanceRef = new AppState();
        } 

        return AppState.instanceRef; 
    }
}

// const appState = new AppState(); // error because of the private constructor

const appState1 = AppState.getInstance(); 

const appState2 = AppState.getInstance();

appState1.counter++;
appState1.counter++;
appState2.counter++;
appState2.counter++;

console.log(appState1.counter); // prints 4 
console.log(appState2.counter); // prints 4

Both console.log() invocations will print 4 as there is only one instance of AppState.

To see this code sample in CodePen, visit this page.

Getting started with TypeScript classes

This blog is a part of my TypeScript series, and the previous ones are:

1. Why program in TypeScript
2. Structural vs nominal typing

In the next several blogs, I’ll focus on object-oriented features of Typescript – classes and interfaces. Let’s start with classes.

First of all, let me remind you that starting from the ECMAScript 2015 spec (a.k.a. ES6), JavaScript supports classes. Being a superset of JavaScript, TypeScript supports all features from JavaScript classes and adds some extras.

For example, JavaScript doesn’t offer syntax for declaring class properties, but TypeScript does. In the screenshot below on the left, you can see how I declared and instantiated the class Person that has three properties. The right side shows the ES6 version of this code produced by the TypeScript compiler:

As you see, there are no properties in the JavaScript version of the class Person. Also, since the class Person didn’t declare a constructor, we had to initialize its properties after instantiating. A constructor is a special function that’s executed only once when the instance of a class is created.

Declaring a constructor with three arguments would allow you to instantiate the class Person and initialize its properties in one line. In TypeScript, you can provide type annotation for constructor’s arguments, but there’s more.

TypeScript offers access level qualifiers public, private, and protected (I’ll cover these in the future blog), and if you use any of them with the constructor arguments, the TypeScript will generate the code for adding these properties in a JavaScript object as in the following screenshot:

Now the code of the TypeScript class (on the left) is more concise and the generated JavaScript code creates three properties in the constructor. We’d like to bring your attention to line 6 in the above screenshot on the left. We declared the constant without specifying its type, but we could have re-written this line explicitly specifying the type of p as follows:

const p: Person = new Person("John", "Smith", 25);

This illustrates an unnecessary use of an explicit type annotation. Since you declare a constant and immediately initialize it with an object of a known type (i.e. Person), the TypeScript type checker can easily infer and assign the type to the constant p. The generated JavaScript code will look the same with or without specifying the type of p. You can try it in the TypeScript playground by following this link.

Regardless if a class has a constructor or it doesn’t, classes allow you to declare custom types that didn’t exist in TypeScript before.

NOTE: We use the public access level with each constructor argument in the TypeScript class, which simply means that the generated corresponding properties can be accessed from any code located both inside and outside of the class.

When you declare the properties of a class, you can also mark them as readonly. Such properties can be initialized either at the declaration point or in the class constructor, and their values can’t be changed afterwards. The readonly qualifier is similar to the const keyword, but the latter can’t be used with class properties.

Getting familiar with class inheritance

In real life, every person inherits some features from his or her parents. Similarly, in the TypeScript world, you can create a new class, based on the existing one. For example, you can create a class Person with some properties and then the class Employee that will _inherit_ all the properties of Person and declare some additional ones.

Inheritance is one of the main features of any object-oriented language. TypeScript has the keyword extends to declare that one class is inherited from the other.

The line 7 in the following screenshot shows how to declare an Employee class that extends the class Person and declares an additional property department. In line 11, we create an instance of the class Employee.

This screenshot was taken from the playground at typscriptlang.org after we entered empl. followed by CTRL-Space on line 13. The TypeScript’s static analyzer recognizes that the type Employee is inherited from Person so it suggests the properties defined in both classes Person and Employee.

In our example, the class Employee is a subclass of Person. Accordingly, the class Person is a superclass of Employee. You can also say that the class Person is an ancestor and Employee is a descendant of Person.

NOTE: Under the hood, JavaScript supports prototypal _object-based_ inheritance, where one object can assign another object as its prototype, and this happens during the runtime. During transpiling to JavaScript, the generated code uses the syntax of the prototypal inheritance as seen in the above screenshot on the right.

In addition to properties, a class can include _methods_ – this is how we call functions declared inside the classes. And if a method(s) is declared in a superclass, it will be inherited by the subclass unless the method was declared with the access qualified private which we’ll discuss a bit later.

The next version of the class Person is shown in the screenshot below, and it includes the method sayHello(). As you can see in line 17, TypeScript included this method in its typeahead help.

You may be wondering, “Is there any way to control which properties and methods of a superclass are accessible from the subclass?”
Actually, a more general question would be “Is there any way to control which properties and methods of a class are accessible from other scripts?” The answer is yes – this is what the private, protected, and public keywords are for, and I’ll cover them in the next blog. Stay tuned…

Why program in TypeScript

A little bit of a JavaScript history

In May of 1995, after 10 days of hard work, Brendan Eich wrote the JavaScript programming language. This scripting language didn’t need a compiler and was meant to be used in the web browser Netscape Navigator. No compilers were needed for deploying a program written in JavaScript in the browser. Adding a tag <script> with the JavaScript sources (or a reference to the file with sources) would instruct the browser to load and parse the code and execute it in the browser’s JavaScript engine. People enjoyed the simplicity of the language – no need to declare types of variables, no need to use any tools – just write your code in a plain text editor and use it in a web page.

JavaScript is a dynamic language, which would give additional freedom for software developers. No need to declare properties of an object as the JavaScript engine would create the property during the runtime if the object didn’t already have it.

Actually, there’s no way to declare the type of a variable. The JavaScript engine will guess the type based on the assigned value (e.g. var x = 123 would mean that x is a number). If later on, the script would have an assignment x = 678, the type of x would automatically change from a number to string.

Did you really want to change the type of x or it’s a mistake? You’ll know it only during the runtime as there is no compiler to warn you about it.

JavaScript is a very forgiving language, which is not a shortcoming if the codebase is small and you’re the only person working on this project. Most likely, you remember that x supposed to be a number, and you don’t need any help with this. And of course, you’ll work your current employer forever so the variable x is never forgotten.

Over the years, JavaScript became super popular and de facto standard programming language of the web. But if 20 years ago we’d use JavaScript just to display web pages with some content and make these pages interactive, today we develop complex web apps that contain thousands of lines of code developed by teams of developers. And you know what? Not everyone in your team remembers that x supposed to be a number.

To be more productive, software developers could help from the tooling like IDE with auto-complete features, easy refactoring et al. But how an IDE can help you with refactoring if the language allows complete freedom in adding properties to objects and changing types on the fly?

Everyone realized that replacing JavaScript in all different browsers with another language is not realistic, so new languages were created. They were more tooling-friendly during development, but the program would still have to be converted to JavaScript before deployment so every browser would support them. TypeScript is one of such languages, and let’s see what makes it stand out.

Why program in TypeScript

TypeScript is a compile-to-JavaScript language, which was released by Microsoft as an open source project in 2012. A program written in TypeScript has to be transpiled into JavaScript first, and then it can be executed in the browser or a standalone JavaScript engine.

The difference between transpiling and compiling is that the latter turns the source code of a program into a bytecode or machine code, whereas the former converts the program from one language to another, e.g. from TypeScript to JavaScript. But in TypeScript community, the word compile is more popular, and I’ll use it to describe the process of conversion of the TypeScript code into JavaScript.

You may wonder, why go through a hassle of writing a program in TypeScript and then compiling it into JavaScript, if you could write this program in JavaScript in the first place? To answer this question, let’s look at the TypeScript from a very high-level perspective.

TypeScript is a superset of JavaScript, which means that you can take any JavaScript file, e.g. myProgram.js, change its name extension from .js to .ts, and the file myProgram.ts becomes a valid TypeScript program without changing a single line of code.

In general, the word superset means that it contains everything that the set has plus something else. The main addition to the “JavaScript set” is that TypeScript also supports static typing whereas JavaScript supports only dynamic typing. Here, the word typing refers to assigning types to program variables.

In programming languages with static typing, a type must be assigned to a variable before you can use it. In TypeScript, you can declare a variable of a certain type, and any attempt to assign to it a value of a different type results in a compilation error. This is not the case in JavaScript, which doesn’t know about the types of your program variables until the runtime. Even in the running program, you can change the type of a variable just by assigning to it a value of different type.

For example, if you declare a variable as a string, trying to assign a numeric value to it will result in the compile-time error.

let customerId: string
customerId = 123; // compile-time error

JavaScript decides on the variable type during the runtime, and the type can be dynamically changed as in the following example:

let customerId = "A15BN"; // OK, customerId is a string
customerId = 123; // OK, from now on it's a number

Now let’s consider a JavaScript function that applies a discount to a price. It has two arguments and both must be numbers.

function getFinalPrice(price, discount) {
   return price - price / discount;
}

How do you know that the arguments must be numbers? First of all, you authored this function some time ago and having an exceptional memory, you may just remember all types of all functions arguments. Secondly, you used descriptive names of the arguments that hint their types. Thirdly, you could guess the types by reading the function code.

This is a pretty simple function, but let’s say someone (not you) would invoke this function by providing a discount as a string, this function would print NaN during runtime.

console.log(getFinalPrice( 100, "10%")); // prints NaN

This is an example of a runtime error caused by the wrong use of a function. In TypeScript, you could provide the types for the function arguments, and such a runtime error would never happen. If someone would try to invoke the function with a wrong type of an argument, this error would be caught as you were typing. Let’s see it in action.

The official TypeScript web page is located at http://www.typescriptlang.org. It offers the language documentation and a playground, where you could enter the code snippets in TypeScript, which would be immediately compiled into JavaScript.

Follow this link, and you’ll see our code snippet in the TypeScript playground, with the squiggly red line under the “10%”. If you hover the mouse over the erroneous code, you’ll see a prompt explaining the error as shown in the screenshot below.

This error is caught by the TypeScript static code analyzer as you type even before you compile this code with tsc. Moreover, if you specify the variable types, your editor or IDE would offer the auto-complete feature suggesting you the argument names and types of the getFinalPrice() function.

Isn’t it nice that errors are caught before runtime? We think so. The vast majority of the developers with the background in such languages as Java, C++, C# take it for granted that the errors are caught during compile time, and this is one of the main reasons why they like TypeScript.

NOTE: There are two types of programming errors – those that are immediately reported by the tools as you type, and those that are reported by the users of your program. Programming in TypeScript substantially decreases the number of the latter.

Still, some of the hard-core JavaScript developers say that TypeScript slows them down by requiring to declare types, and in JavaScript, they’d be more productive. But the majority of the web developers are not JavaScript ninjas and can appreciate a helping hand offered by TypeScript.

There are more than a hundred programming languages that are compiled to JavaScript, but what makes TypeScript stand out is that its creators follow the ECMAScript standards and implement the upcoming JavaScript features a lot faster than Web browsers vendors.

You can find the current proposals of the new ECMAScript features here. A proposal has to go through several stages to be included in the final version of the next ECMAScript spec. If a proposal makes it to Stage 3, most likely it’s included in the latest version of TypeScript.

In the Summer of 2017, the async and await keywords were included into the ECMAScript specification ES2017, a.k.a. ES8. It took more than a year for major browsers to start supporting these keywords. But TypeScript supported them since November of 2015. This means that TypeScript developers could start using these keywords about three years earlier than those who waited for the browsers’ support.

And the best part is that you can use the future JavaScript syntax in today’s TypeScript code and compile it down to the older JavaScript syntax (e.g. ES5) supported by all browsers!

Having said that, we’d like to make a clear distinction between the syntax described in the latest ECMAScript specifications, and the syntax that’s unique to TypeScript. That’s why we recommend you to read the Appendix A first, so you know where ECMAScript ends and TypeScript begins.

Although JavaScript engines do a decent job of guessing the types of variables by their values, development tools have a limited ability to help you without knowing the types. In mid- and large-size applications, this JavaScript shortcoming lowers the productivity of software developers.

The generated JavaScript code is easy to read, and it looks like hand-written code.

TypeScript follows the latest specifications of ECMAScript and adds types, interfaces, decorators, class member variables (fields), generics, enums, the keywords public, protected, and private and more. Check the TypeScript roadmap to see what’s available and what’s coming in the future releases of TypeScript.

Five facts about TypeScript
***************
1. The core developer of TypeScript is Andres Hejlsberg, who also designed Turbo Pascal and Delphi, and is the lead architect of C# at Microsoft.

2. At the end of 2014, Google approached Microsoft asking if they could introduce decorators in TypeScript so this language could be used for developing of the Angular 2 framework. Microsoft agreed, and this gave a tremendous boost to the TypeScript popularity given the fact that hundreds of thousands of developers use Angular.

3. As of September of 2018, the TypeScript compiler had more than three million downloads per week from npmjs.org, and this is not the only TypeScript repository. For current statistics, visit this page.

4. As per Redmonk, a respectful software analytics firm, TypeScript came 14th in the programming language rankings chart in January of 2018.

5. According to the StackOverflow Survey 2018, TypeScript is the fourth most loved language.
***************

And one more thing. Some JavaScript developers are still in denial and say, “If I’ll be programming in TypeScript, I’ll need to introduce an extra step between writing code and seeing it running – the compilation.” When I hear such an argument, I want to ask, “Do you really want to stick to the ES5 version of JavaScript ignoring all the latest syntax introduced by ES6, 7, 8, and 9? If not, then you’ll have the compilation step in your workflow anyway – compile a newer JavaScript into the ES5 syntax.”

To continue getting familiar with TypeScript, read about the structural type system here.

Learning TypeScript: Structural vs nominal typing systems

After completing the second edition of the book “Angular Development with TypeScript“, my colleague Anton Moiseev and I started working on yet another book for Manning. This one will be called “TypeScript Quickly” and its tentative Table of Contents is available here.

This book will cover the main syntax elements of the TypeScript language, and to make the book more interesting, we’ll also develop a blockchain app.
Meanwhile, I’ll start a series of blogs on the TypeScript-related topics. This one is about TypeScript’s structural type system.

A primitive type has just a name (e.g. number) while a more complex type like an object or class has a name and some structure represented by properties (e.g. a class Customer has properties name and address).

How would you know if two types are the same or not? In some languages (e.g. Java) two types are the same if they have the same names, which represents a nominal type system. In Java, the last wouldn’t compile because the names of the classes are not the same even though they have the same structure:

class Person {
	String name;
}

class Customer {
	String name;
}

Customer cust = new Person();  // compiler's error

But TypeScript and some other languages use the structural type system. In the following code snippet I re-wrote the above code snippet in TypeScript:

class Person {
	name: string;
}

class Customer {
	name: string;
}

const cust: Customer = new Person(); // no errors  

This code doesn’t report any errors because TypeScript uses structural type systems, and since both classes Person and Customer have the same structure, it’s OK to assign an instance of one class to a variable of another.

Moreover, you can use object literals to create objects and assign them to class-typed variables or constants as long as the shape of the object literal is the same. The following code snippet will compile without errors:

class Person {
	name: string;
}

class Customer {
	name: string;
}

const cust: Customer = { name: 'Mary' };   
const pers: Person = { name: 'John' };

Our classes didn’t define any methods, but if both of them would define a method(s) that has the same signature (name, arguments, and the return type) they would also be compatible.

What if the structure of Person and Customer are not exactly the same? Let’s add a property age to the class Person as is the following listing:

class Person {
    name: string;
    age: number;    // 1
}

class Customer {
	name: string;
}

const cust: Customer = new Person(); // still no errors  

1 We’ve added this property

Still no errors! TypeScript sees that Person and Customer have the same shape. We want to use the constant of type Customer (it has the property name) to point at the object of type Person (it also has the property name).

Follows the link https://bit.ly/2MbHvpH and you’ll see this code in TypeScript playground (a REPL to try code snippets in TypeScript and compile them into JavaScript). Click Ctrl-Space after the dot in cust. and you’ll see that only the name property is available even though the class Person has also the property age.

Homework: Can the class Customer have more properties than Person?
In the previous code snippet, the class Person had more properties than Customer and the code compiled without errors. What if the class Customer has more properties than Person? Would the following code compile? Explain your answer.

class Person {
    name: string;
}

class Customer {
    name: string;
    age: number;
}

const cust: Customer = new Person();

As they say, “If it walks like a duck and it quacks like a duck, then it must be a duck”. That’s why structural typing is also known as duck typing. If an object can be used for a particular purpose, use it. Yes, it’s not a duck, but at least it walks like a duck, which is all that matters in this context.

How I migrated a dozen of projects to Angular 6 and then 7

In this article, I’ll share with you my experience of upgrading more than a dozen of Anguar 5 projects to Angular 6. These projects were small to medium in size, but they used lots of various Angular features because these are the projects from the second edition of our Angular book. Many of these projects had multiple apps configured in the file .angular-cli.json, and they were automatically migrated into the new project structure as defined in the new configuration file angular.json.

First of all, there’s the site https://update.angular.io that gives you an idea of how to do the upgrade from version X to version Y, and you certainly need to read the instructions there first. But the devil is in the detail, right?

Theoretically, the upgrade should be a 1-2-3 process that consists of the following three steps:

1. npm install @angular/cli@latest –save-dev
Run this command in your project’s dir, to upgrade (and install) the latest Angular CLI version in the devDependencies section of package.json. This command shouldn’t need @latest, but it does.

2. ng update @angular/cli
Run this command to convert the project configuration file .angular-cli.json into angular.json introduced by Angular 6.It also will update testing and tslint config files.

3. ng update @angular/core
Run this command to upgrade all Angular dependencies in the package.json file (except Angular Material and Angular Flex Layout, if used).

What else is needed

On my computer, I had Angular CLI 6 install globally, and my typical project had the line “typescript”: “~2.4.2” in devDependency section of package.json.

Before running and upgrade steps, bump up the TypeScript compiler version in your project or you’ll get an error “@angular/compiler-cli” has an incompatible peer dependency to “typescript” during the step 3. Start any project upgrade with manually changing this dependency to “typescript”: “~2.7.2”. If you still see that error, delete the node_module directory and re-run step 3.

If you use the Angular Material library, run ng update @angular/material to update its dependencies in package.json.

If you use the Flex Layout library, modify its version to 6.0.0-beta15 or later prior to running ng update @angular/core.

Your project’s .angular-cli.json might include the file favicon.ico in the asset’s property that’s not used in your app. Angular 5 would still launch your app even if this file was missing. In Angular 6, you need to explicitly remove all occurrences of favicon.ico in the newly generated angular.json.

After migration, I noticed some strange behavior in the UI rendering, which seems like a bug. In some of my apps, I had the following HTML in the component templates:

<a [routerLink]="['/']">Home</a> 
<a [routerLink]="['/product']">Product</a> 

In Angular 5, it rendered just fine, but after migration to Angular 6, the browser rendered both links without the space between them: HomeProduct. Adding &nbsp; after the first anchor tag helped. I thought it might be related to the Angular compiler’s option preserveWhitespaces, but it didn’t.

Starting from TypeScript 2.7, you may need to take care of the error TS2564: Property ‘SoAndSo’ has no initializer and is not definitely assigned in the constructor. For example, the following class variable declaration won’t compile:

product: Product[];

Either set the TypeScript compiler’s option strictPropertyInitialization to false or explicitly initialize class variables, e.g.

product: Product[] = [];

Upgrading your app to RxJS 6

During the upgrade, I spent the most time updating the code related to breaking changes in RxJS 6.

Your updated package.json will include the dependency “rxjs-compat”: “^6.0.0-rc.0” after step 3. At the time of this writing, the current version of rxjs-compat is 6.1.0, so if you decide to keep rxjs-compat, update its version in package.json and reinstall dependencies. Theoretically, having the rxjs-compat package should allow you to run your app without making any changes in the app code that uses RxJS API. In practice, this may not be the case and the app may fail either during the build- or runtime.

So I decided to remove the rxjs-compat dependency and modify my code to conform to RxJS 6 structure. Remove rxjs-compat from your package.json file to avoid unnecessary increase of your app bundle size. Then run ng serve and fix the RxJS errors (if any) one by one. Then load your app in the browser and keep the browser console wide open so you won’t miss the RxJS-related runtime errors, if any.

The internal structure of RxJS 6 has changed, and you need to change the import statements to get the classes and operators from the proper places. You may start with reading this upgrade guide. Disclaimer: I didn’t follow my own advice and started learning by doing.

In the past, the golden rule was “Don’t import Observable from rxjs, import it from rxjs/observable otherwise the entire RxJS library will be included in your app bundle”. No more. The new golden rule is import { Observable } from “rxjs”; The same applies to Subject, Subscription, interval(), of(), and many other RxJS thingies.

You need to stop using the dot-chainable operators (they simply won’t work without rxjs-compat package). Now you have to use the RxJS pipeable operators, and your imports should look like this:
import { debounceTime, map } from ‘rxjs/operators’;

The ng update command added the rxjs-compat package to your project, and if you’re lucky, your app might run as before without changing the code. But some of my apps gave me build errors, while others crashed at runtime.

For example, in one of my apps, I had this:

import { Observable } from "rxjs";
...
const myObservable$ = Observable.fromEvent(...)

Got the TypeScript error “error TS2339: Property ‘fromEvent’ does not exist on type ‘typeof Observable’.” Here’s the fix:

import { fromEvent } from "rxjs";
...
const myObservable$ = fromEvent(...)

In another app, I had this:

import {Observable} from 'rxjs';
...
return Observable.empty();

It also gave me the error TS2339. This time the fix included replacing the deprecated function empty() with the constant EMPTY:

import {EMPTY} from 'rxjs';
...
return EMPTY;

Another app had this:

numbers$ = Observable.interval(1000)...

This code sneaked through the build phase, but crashed my app during runtime. Here’s the fix:

import {interval} from "rxjs";
numbers$ = interval(1000)...

Don’t bet too heavily on rxjs-compat. This package may help you to quickly get your app running in Angular 6, but until you remove rxjs-compat from your project, don’t report to your boss that migration is done. Find the time and fix the code in your Angular 5 app to conform to RxJS 6. After this is done, migrate your app to Angular 6.

The next one is for those two people who also use RxJS WebSocketSubject. The API has changed in RxJS 6. In the past, you’d do this:

import { WebSocketSubject } from 'rxjs/observable/dom/WebSocketSubject';
...
let myWebSocket = WebSocketSubject.create(wsUrl);
...
myWebSocket.next(JSON.stringify(objectToSend));

To make it work in RxJS 6, I’ve changed it to the following:

import { WebSocketSubject } from 'rxjs/websocket';
...
let myWebSocket = new WebSocketSubject(wsUrl);
...
myWebSocket.next(objectToSend);

And one more thing. If you use Angular Material library, you may run into some breaking changes in the UI components. But overall, conversion of a project to Angular 6 is not a time-consuming process.

P.S. If you use NGRX, don’t forget to upgrade all ngrx packages to version 6 (at the time of this writing, it’s 6.0.0-beta.3).

Update. Yesterday, I’ve upgraded all these projects to Angular 7. In each project I ran just one command that updated dependencies in package.json:

ng update –all

This was easy.