Book Image

Learning Angular - Fourth Edition

By : Aristeidis Bampakos, Pablo Deeleman
5 (1)
Book Image

Learning Angular - Fourth Edition

5 (1)
By: Aristeidis Bampakos, Pablo Deeleman

Overview of this book

As Angular continues to reign as one of the top JavaScript frameworks, more developers are seeking out the best way to get started with this extraordinarily flexible and secure framework. Learning Angular, now in its fourth edition, will show you how you can use it to achieve cross-platform high performance with the latest web techniques, extensive integration with modern web standards, and integrated development environments (IDEs). The book is especially useful for those new to Angular and will help you to get to grips with the bare bones of the framework to start developing Angular apps. You'll learn how to develop apps by harnessing the power of the Angular command-line interface (CLI), write unit tests, style your apps by following the Material Design guidelines, and finally, deploy them to a hosting provider. Updated for Angular 15, this new edition covers lots of new features and tutorials that address the current frontend web development challenges. You’ll find a new dedicated chapter on observables and RxJS, more on error handling and debugging in Angular, and new real-life examples. By the end of this book, you’ll not only be able to create Angular applications with TypeScript from scratch, but also enhance your coding skills with best practices.
Table of Contents (17 chapters)
Other Books You May Enjoy


Working with TypeScript or any other coding language means working with data, and such data can represent different sorts of content that are called types. Types are used to represent the fact that such data can be a text string, an integer value, or an array of these value types, among others. You may have already met types in JavaScript since we have always worked implicitly with them. This also means that any given variable could assume (or return, in the case of functions) any value. Sometimes, this leads to errors and exceptions in our code because of type collisions between what our code returned and what we expected it to return type-wise. We can enforce this flexibility using a specific type called any, as we will see later in this chapter. However, statically typing our variables gives our IDE and us a good picture of what kind of data we are supposed to find in each instance of code. It becomes an invaluable way to help debug our applications at compile time before the code is executed.


One of the most widely used primitive types is the string, which populates a variable with a piece of text:

var brand: string = 'Chevrolet';

Check out the type definition next to the variable name, separated by a colon. It is the way to annotate types in TypeScript.

We can use single or double quotes for the value of a string variable. Feel free to choose either and stick with it within your team. We can define multiline text strings with support for text interpolation using placeholder variables and backticks:

var brand: string = 'Chevrolet';
var message: string = `Today it's a happy day! I just bought a new ${brand} car`;

In the preceding snippet, any variables that we may use inside the multiline text must be surrounded by the curly braces of the placeholder ${}.

Declaring variables

TypeScript, as a superset of JavaScript, supports expressive declaration nouns such as let, which denotes that the scope of the variable is the nearest enclosing block (either a function, for loop, or any other enclosing statement). On the other hand, const indicates that the value of the declared variable cannot be changed once it’s set.

The let keyword

Traditionally, developers have been using the keyword var to declare objects, variables, and other artifacts, but this is discouraged when you start using ES6 or TypeScript. The reason is that ES5 only has a function scope; that is, a variable is unique within the context of a function:

function test() {
    var x;

There can be no other variable declared as x in this function. If you do declare one, then you effectively redefine it. However, there are cases in which scoping is not applied, such as in loops. For example, in Java, you would write the following and ensure that a variable will never leak outside of the loop:

var i = 3;
for (var i = 0; i < 10; i++) {

In the preceding snippet, the i variable outside the loop will not affect the i variable inside it because they have a different scope. To overcome this limitation, ES6 introduced the let keyword:

let i = 3;
for (let i = 0; i < 10; i++) {

So, remember, no more var; use the let keyword wherever possible.

The const keyword

The const keyword is a way to indicate that a variable should never change. As a code base grows, changes may happen by mistake, which can be costly. The const keyword can prevent these types of mistakes through compile-time support. Consider the following code snippet:

const PI = 3.14;
PI = 3;

If we try to run it with TypeScript, the compiler will throw the following error message:

Cannot assign to 'PI' because it is a constant

The preceding error will come up only at the top level. You need to be aware of this if you declare objects as constants, like so:

const obj = {
    a: 3
obj.a = 4; 

If we declare the obj variable as a constant, it does not prevent the entire object from being edited but rather its reference. So, the preceding code is valid. If we try to change the reference of the variable such as obj = {}, it is not allowed, and we get the same compiler error.

Prefer to use the const keyword when you are sure that the properties of an object will not change during its lifetime. It prevents the object from accidentally changing and enforces data immutability, a hot topic in Angular applications.


The number type is probably the other most widespread primitive data type, along with string and boolean:

const age: number = 7;
const height: number = 5.6;

It defines a floating-point number and hexadecimal, decimal, binary, and octal literals.


The boolean type defines a variable that can have a value of either true or false:

const isZeroGreaterThanOne: boolean = false;

The result of the variable represents the fulfillment of a boolean condition.


The array type defines a list of items that contain certain types only. Handling exceptions that arise from errors such as assigning wrong member types in a list can now be easily avoided with this type.

The syntax requires the postfix [] in the type annotation, as follows:

const brands: string[] = ['Chevrolet', 'Ford', 'General Motors'];
const ages: number[] = [8, 5, 12, 3, 1];

If we try to add a new item to the ages array with a type other than a number, the runtime type-checker will complain, making sure our typed members remain consistent and that our code is error-free.

Dynamic typing with no type

Sometimes, it is hard to infer the data type from the information we have at any given point, especially when we are porting legacy code to TypeScript or integrating loosely typed third-party libraries and modules. TypeScript supplies us with a convenient type for these cases. The any type is compatible with all the other existing types, so we can type any data value with it and assign any value to it later:

let distance: any;
distance = '1000km';
distance = 1000;
const distances: any[] = ['1000km', 1000];

However, this great power comes with great responsibility. If we bypass the convenience of static type checking, we are opening the door to type errors when piping data through our modules. It is up to us to ensure type safety throughout our application.

Custom types

In TypeScript, you can come up with your own type if you need to by using the type keyword in the following way:

type Animal = 'Cheetah' | 'Lion';

It is essentially a type with a finite number of allowed values. Let’s create a variable of this type:

const animal: Animal = 'Cheetah';

The preceding code is perfectly valid as Cheetah is one of the allowed values and works as intended. The interesting part happens when we give our variable a value it does not expect:

const animal: Animal = 'Turtle';

The preceding code will result in the following compiler error:

Type '"Turtle"' is not assignable to type 'Animal'


The enum type is a set of unique numeric values that we can represent by assigning user-friendly names to each one. Its use goes beyond assigning an alias to a number. We can use it to list the variations that a specific type can assume in a convenient and recognizable way. It begins numbering members, starting at 0 unless explicit numeric values are assigned to them:

enum Brands { Chevrolet, Cadillac, Ford, Buick, Chrysler, Dodge };
const myCar: Brands = Brands.Cadillac;

In the preceding code, if we inspect the variable myCar, we will see that it returns the value 1, which is the index of Cadillac. As we mentioned already, we can also assign custom numeric values like the following:

enum BrandsReduced { Tesla = 1, GMC, Jeep };
const myTruck: BrandsReduced = BrandsReduced.GMC;

In the preceding code, if we inspect the variable myTruck, we will see that it returns the value 2 because the first enumerated value, Tesla, was set to 1 already. We can extend value assignation to all members as long as such values are integers:

enum StackingIndex {
    None = 0,
    Dropdown = 1000,
    Overlay = 2000,
    Modal = 3000
const mySelectBoxStacking: StackingIndex = StackingIndex.Dropdown;

One last point worth mentioning is the possibility to look up a member mapped to a given numeric value:

enum Brands { Chevrolet, Cadillac, Ford, Buick, Chrysler, Dodge };
const myCarBrandName: string = Brands[1];

In the preceding snippet, the myCarBrandName variable will be equal to Cadillac.

It should also be mentioned that from TypeScript 2.4 and onward, it is possible to assign string values to enums. It is a technique preferred in Angular projects because of its extended support in template files.


The void type represents the absence of a type, and its use is constrained to annotating functions that do not return an actual value:

function test(): void {
    const a = 0;

In the preceding snippet, there is no return type in the function.

Type inference

Typing is optional since TypeScript is smart enough to infer the data types of variables and function return values out of context with a certain level of accuracy. If it is not possible, it will assign the dynamic any type to the loosely typed data at the cost of reducing type checking to a bare minimum.

In the following section, we will embark on a new journey through TypeScript to learn more about TypeScript functions and their execution flow.