Types in Typescript plainly
Tags: typescript, angular, beginners
Published: 2022-03-17 12:40:39

From the beginning, Typescript was presented as JavaScript improvement with addition of types. But why? More restrictions make less flexibility. We want to do whatever we want. For example, in JavaScript I can do the following:
```javascript
let a = 42;
a = 'bunny';
let b = a / 2;
```
This code is legit in JavaScript. However, what will happen during runtime? `b` will get the value of `NaN`, not a number. And, if somewhere later on in our program we'll use `b` it can bring us to runtime error. In Typescript this code will not compile because we can't assign `string` value to variable, that is `number`. As a result, it will save us much debugging time and struggle with bugs.

Strict types allow preventing many runtime errors during development stage. Typescript allows usage of scalar and compound types. All scalar types are derived from JavaScript and equivalent to them. Compound types are extension of JavaScript `object`. By that, it shows the issues at compilation moment instead of runtime.


## Compound types
Typescript allows describing the shape of application data by classes, interfaces and types. Classes are regular JavaScript classes and OOP is out of scope of this article. Additionally, Typescript suggests us to use interfaces and types. The key difference with classes is that interfaces and types are deleted by compiler. This limits their usage. For example, we can use keyword `new` with classes only. When we need to decide if we need to use a class or interface, we need to answer the question "Do I need to create an instance of this type?" The difference between interface and type is that we cannot extend type, but we can combine it with other types using logical operators (&, |). Classes can implement multiple interfaces and this is the only way of multiple inheritance in Typescript.


## Annotation
By default, just declared variable has type `any`, that is self-explanatory. It means that we can assign value of any type to this variable. And it is definitely unacceptable in our world of law and order. To make variable strictly typed, we need to annotate it. Annotation is telling the compiler which type of data we can assign to this variable.

```typescript
let a: number;
let b: boolean;
```
If we won't annotate the variable, it will have type `any`. In strict mode of the compiler (that must be default in all of our projects), we will get error about it.


## Inference
Typescript has a type inference engine built in. It means that it can automatically detect the type of expression. To achieve benefits of this technology, we must initialize variables during declaration.

```typescript
let a = 42;
```
`a` automatically will have type of number. The declaration with annotation will legit as well.

```typescript
let a: number = 42;
```
However, we should avoid this way. The following example straightforwardly illustrates the benefit of inference.

```typescript
const a: string = 'Kirk';
```

The type of `a` is string. 
If we use inference:

```typescript
const a = 'Kirk';
```
the type of `a` is "Kirk", that makes `a` much more precise.

Let's look at the following example:
```typescript
type Names = 'Jim' | 'Spock' | 'Leonard';

function processName(name: Names) {}

const name1: string = 'Jim';
const name2 = 'Jim';

processName(name1);

processName(name2);
```
Calling function `processName` with `name1` won't compile because argument of type 'string' is not assignable to parameter of type 'Names'.


There are cases when inference doesn’t work well. For example, if we initialize our variable by array of objects, that are instances of classes that extend one base class, we will have array of common type that will be combination of those children's classes. In this case we will want to manually annotate the variable as array of base class.


Sometimes the compiler gets confused. Usually, we should consider it as a gap in types architecture and probably revise it.

## Functions
Highly important to specify functions returning types. Of course, Typescript can infer it from `return` statement. However, when we start to construct our function and annotate it, IDE will help us to return the correct type. 

## RxJS
Starting with version 7 of RxJS the typing was highly improved. And this is a good reason for upgrade of your projects. There is almost no need any more to annotate projection functions arguments, even after `filter`. 

## Conclusion
Understanding and usage of types is cornerstone of modern front-end development. We should always use inference wherever it's possible. We should always specify the return type of our methods and functions. And we should almost never use `any`.


Photo by <a href="https://unsplash.com/@youdiful?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Judith Frietsch</a> on <a href="https://unsplash.com/s/photos/types?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>