Book Image

Learn TypeScript 3 by Building Web Applications

By : Sebastien Dubois, Alexis Georges
Book Image

Learn TypeScript 3 by Building Web Applications

By: Sebastien Dubois, Alexis Georges

Overview of this book

TypeScript is a superset of the JavaScript programming language, giving developers a tool to help them write faster, cleaner JavaScript. With the help of its powerful static type system and other powerful tools and techniques it allows developers to write modern JavaScript applications. This book is a practical guide to learn the TypeScript programming language. It covers from the very basics to the more advanced concepts, while explaining many design patterns, techniques, frameworks, libraries and tools along the way. You will also learn a ton about modern web frameworks like Angular, Vue.js and React, and you will build cool web applications using those. This book also covers modern front-end development tooling such as Node.js, npm, yarn, Webpack, Parcel, Jest, and many others. Throughout the book, you will also discover and make use of the most recent additions of the language introduced by TypeScript 3 such as new types enforcing explicit checks, flexible and scalable ways of project structuring, and many more breaking changes. By the end of this book, you will be ready to use TypeScript in your own projects and will also have a concrete view of the current frontend software development landscape.
Table of Contents (15 chapters)

Variables declaration

In the previous code sample, we used the familiar var keyword of JavaScript to declare our variable.

Before we code anything else together, you really need to know that var is a keyword that you should forget about and never use again.

Why? The issue is that var does not support block scope. Instead, variables declared with var are function-scoped and any variable declarations in a block will get hoisted to the surrounding function.

Hoisting is a weird JavaScript concept. In JavaScript, variable declarations (and declarations in general) are treated first, before anything else is executed. This means that declaring a variable anywhere is exactly the same as declaring it at the top. This also means that a variable can be used before it is declared, which is counter-intuitive, to say the least.

This might sound unclear, so let us give you an example:

var a = 12;
var result = a + b;
var b = 30;
console.log("Result: ",result);

The previous code is a perfectly valid JavaScript code (but is certainly not recommended).

Up until ES5, var was the only way to declare variables, but this has changed with ES2015, which has introduced two new keywords: let and const. Both of these keywords do support block scope.

The let keyword is the safer alternative to var, while const allows you to define constants.

We are putting constants between quotes because the const keyword does not make objects immutable; it only ensures that the variable cannot be reassigned, but the contents of the object it points to can be modified.

Here is the recommended order of preference: const > let > var.

Why? As you'll see throughout the book, defensive programming has many merits and can help you write better and safer code. While programming defensively, you'll notice that immutability has many benefits, for example, to avoid side effects and surprises.

In practice, even if const does not guarantee immutability, it is still a step in the right direction and it clearly conveys the intent of your code, which is very important. Hence, our recommendation is to use const whenever possible and to only use let when you need to be able to assign different values.

Basic TypeScript types

Before we go on, let's see what basic types are supported by TypeScript:

  • boolean: true or false.
  • number: Floating point values. Those can be expressed in hexadecimal, decimal, binary, and octal forms.
  • string: can be delimited by single quotes ('), double quotes ("), or back-ticks (`) to define template literals (also known as template strings).

Here are some examples of numbers:

  • let decimal: number = 42
  • let hexadecimal: number = 0x42
  • let binary: number = 0b101010
  • let octal: number = 0o52

Here are some string examples:

  • let hello: string = 'Hello'
  • let world: string = "World" // same as above
  • let cool: string = `${hello} ${world}!`

Template strings are very useful—they make it really easy to embed expressions. In the preceding example, we've just included another string, but in a template string expression, you could also invoke functions, perform calculations, and so on. Template strings usually help improve code readability. Note that string templates are actually a feature of ES2015 (that TypeScript supports by default).

You can also define multiline template literals!

TypeScript also supports other basic types that we will cover later on: arrays, tuples, enums, any, void, null, undefined, never, and object.

A tiny bit of type safety can't hurt

To wrap this chapter up, let's write another example. This time, we will write an unsafe program and then we will see how we can make it safer using TypeScript.

Our program will be a simple calculator. For the sake of the example, our calculator will only be able to multiply values together, but don't hesitate to extend the example to include other operations as well.

Create a new file and call it calculator.ts. In that file, add the following code:

function multiply(a, b) {
const result = a * b;
console.log("The multiplication of "+a+"*"+b+" equals to :
"+result);
return result;
}

multiply(1, 2);
multiply(2,2);
multiply(-10,10);
//multiply('foo', "bar");

We've used const this time because the calculation result should never be changed.

If you now compile and execute this calculator (using tsc calculator.ts, remember?), you'll see the results of our calls to the multiply function.

Everything seems fine so far, as shown here:

$ node calculator-unsafe.js
The multiplication of 1*2 equals to : 2
The multiplication of 2*2 equals to : 4
The multiplication of -10*10 equals to : -100

However, that code isn't very safe. What if you uncomment the last line? Do you think it makes sense to multiply strings together when doing calculations?

Now, indeed, the output is more problematic:

$ node calculator-safer.js
The multiplication of 1*2 equals to : 2
The multiplication of 2*2 equals to : 4
The multiplication of -10*10 equals to : -100
The multiplication of foo*bar equals to : NaN

Is this a behavior that you had intended? Probably not! The main problem that you have here, since that code is actually again mostly JavaScript, is one of expressiveness; you cannot easily/clearly state which types you expect as an input of the function. This is really unsafe because you could pass just about anything to your function.

You can, of course, write safer code in JavaScript, but at the expense of readability and conciseness.

Now, let's see how TypeScript can help. Actually, without you knowing, it already does!

Try to add this line to the code: multiply(1). This lacks an expected parameter. In pure JavaScript code, this would be alright, but TypeScript's compiler does complain now: TS2554: Expected 2 arguments, but got 1.

Let's go further now. Adapt the code as follows to specify the types that you expect:

function multiply(a: number, b: number) {
const result: number = a * b;
console.log(`The multiplication of ${a}*${b} equals to
${result}`);
return result;
}

multiply(1, 2);
multiply(2,2);
multiply(-10,10);
multiply("foo", 'bar');

We now have changed the console.log call to make use of a template string. Doesn't this make the code more readable? Also, take a look at the generated JavaScript code for this line: console.log("The multiplication of " + a + "*" + b + " equals to " + result);. As you can see, TypeScript has replaced our template string, making the code compatible with ES3.

As you can see, we can easily specify variable types using the : type notation, including for function parameters.

If you try to compile the program again, you'll see that TypeScript now helps us to avoid more mistakes:

$ tsc calculator-safer.ts
calculator.ts:10:10 - error TS2345: Argument of type '"foo"' is not assignable to parameter of type 'number'.
10 multiply("foo", "bar");
~~~~~

Isn't this wonderful? But wait, there's so much more yet to discover!