Understanding Advanced Concepts in Typescript
Tags: typescript, javascript, advanced
Published: 2020-07-15 18:20:58

This article was written by Aaron Xie and was originally published at [Educative, Inc](educative.io/blog). 

When using JavaScript, many developers know the headache of debugging. You run a program. Find a new bugs. Rinse and repeat. After hours of debugging, you’ve finally fixed your problem. This is a common problem with a programming language like JavaScript that doesn’t compile. 

In an effort to solve the shortcomings of JavaScript, Microsoft created TypeScript. As larger teams realize the benefits of adopting TypeScript into their technology stack, more and more developers are required to know it. 

Today, you are going to learn some advanced concepts in TypeScript so that you are your way to becoming an expert.

**You will be learning:**

- What is TypeScript?

- Advantages and limitations of TypeScript

- Intro to Strict types

- TypeScript and Object-oriented programming

- Types in TypeScript

- Other topics to learn

- Wrapping up and resources

<br>

## What is TypeScript?

Created and maintained by Microsoft, [TypeScript](https://www.educative.io/blog/typescript-tutorial) is a superset of JavaScript, meaning that all functional JavaScript code is valid under TypeScript. The language can be understood as "JavaScript for application-scale development," with two primary focuses:

- **Provide features from future JavaScript engines to current JavaScript engines**

- **Provide a type system for JavaScript**

The components of TypeScript are typically the language itself, which is essentially JavaScript plus additional features and syntax, the compiler that converts the code into JavaScript, and the language service, which provides editor-like applications near the end of the compiler pipeline.

So, why use TypeScript?

- **Typing:** TypeScript offers [static typing](https://www.educative.io/edpresso/statically-v-dynamically-v-strongly-v-weakly-typed-languages), which many large teams like Microsoft and Google have found beneficial to streamline the development process.

- **Object-oriented programming:** TypeScript supports object-oriented programming concepts like interfaces, [inheritance](https://www.educative.io/blog/understanding-and-using-prototypal-inheritance-in-javascript), classes, and more.

- **Compilation:** Unlike JavaScript, which is an interpretative language, TypeScript compiles the code for you and finds compilation errors, which make it easier to debug.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/sy4gy4b4yh0k98f9vkvc.png)

### Installing TypeScript

Before we dive into TypeScript, make sure that you have successfully installed TypeScript. The two primary ways to get the TypeScript tools is through npm, the Node.js package manager, or by installing TypeScript's visual studio plugins.

NPM:

**Install**
<pre style="font-size:16px;">
> npm install -g typescript
</pre>

**Compile**
<pre style="font-size:16px;">
> tsc helloworld.ts
</pre>

If you aren't using NPM, you can download TypeScript through this [link](https://www.typescriptlang.org/#download-links).

## Advantages and limitations of TypeScript

### Typing

JavaScript is a dynamically typed language, meaning that type errors are found only during runtime. This can be a significant downside for large teams working on complex projects, as finding all mistakes to the code beforehand would be significantly easier. 

TypeScript offers optional static typing so that a variable can't change its types and can only accept certain values. This typing helps the TypeScript compiler find more bugs so that developers are working with less error-prone code. Type guards create more structure for the code by making it more readable, and more easily refactored.

> Interested in learning about more differences between JavaScript and TypeScript? You can learn more here: [What's the difference between JavaScript and TypeScript?](https://www.educative.io/edpresso/whats-the-difference-between-javascript-and-typescript) 

### IDE support

Because TypeScript offers types, text editors and integrated development environments (IDE) can provide more helpful information to developers. These environments can offer auto-completion, code navigation, error flagging and more to increase the productivity of teams. 

Some popular environments that support TypeScript 3:

- Microsoft Visual Studio

- WebStorm

- Visual Studio Code

- Atom

- Eclipse

### Browser compatibility

Browser compatibility is one of the powerful features that TypeScript offers. The TypeScript compiler transforms your code to make it compatible with all the modern browsers. This compatibility is because the compiler is able to translate the TypeScript code into vanilla JS, which all devices, platforms, and browser support.

Though there are many advantages to using TypeScript, it's not a perfect solution. One downside to improving your code readability is that you have to write more code, which can potentially increase your development time. It also increases the size of your TypeScript files compared to using vanilla JavaScript.

> ## Become a TypeScript developer.
Educative's **Learn  TypeScript** course allows complete beginners to learn the primary concepts to become a full-fledged TypeScript developer.
>
><b>[Learn TypeScript: The Complete Course for Beginners](https://www.educative.io/courses/learn-typescript-complete-course) </b>
>
## Already a TypeScript learner?
>
> Tackle the advanced concepts and improve your TS skills with hands-on practice. 
> 
> <b>[Advanced TypeScript MasterClass](https://www.educative.io/courses/advanced-typescript-masterclass)


<br>

## Intro to Strict Types

Now that we have a sense of what TypeScript has to offer, let's dive into some of the more advanced concepts that make TypeScript a powerful tool.

### `noImplicitAny`

According to the documentation, the definition of `noImplicitAny` is to "raise errors on expressions and declarations with any implied any type."

This means that whenever TypeScript can infer a type, you will get an error if you allow `noImplicitAny`. This example can be seen by passing function arguments.

```ts
function print(arg) {
    send(arg);
}

print("hello");
print(4);
```

In the above code, **what are valid arguments for the `print` function?** If you don't add a type to the function argument, TypeScript will assign the argument of type `any`, which will turn off type checking. 

For developers who prefer safety in their code, they can utilize `noImplicityAny`, which will notify them of any possibilities for type `any` in their code. Let's see what will happen with the same `print` function.

```ts
function print(arg) { // Error : someArg has an implicit `any` type
    send(arg);
}
```

To fix the error, you can annotate the function argument.

```ts
function print(arg: number) { // Error : someArg has an implicit `any` type
    send(arg);
}
```
But if you still want type `any`, you can explicitly mark the argument as `any`.

```ts
function print(arg: any) { // Error : someArg has an implicit `any` type
    send(arg);
}
```

### `unknown`

The `unknown` type is similar to the `any` type in that all types are assignable to the `any` and `unknown` type, but the distinction is that the `any` type is assignable to any other types, but the `unknown` type is un-assignable to any other type.  The distinction can be a confusing concept, so let's take a look at an example.

```ts
function example1(arg: any) {
  const a: str = arg; // no error
  const b: num = arg; // no error
}

function example2(arg: unknown) {
  const a: str = arg; // 🔴 Type 'unknown' is not assignable to type 'string'.(2322)
  const b: num = arg; // 🔴 Type 'unknown' is not assignable to type 'number'.(2322)
}
```

A variable `arg` is passed to both functions, which can have a type of `string`, `number`, or another type. No matter its type, `arg` is then assigned the type `any` and `unknown`. 

However, unlike the `any` type, a variable of `unknown` type cannot then be assigned to another type, as seen in lines 7 and 8. The `any` type is bidirectional, whereas `unknown` is unidirectional.

The `unknown` type can be helpful in cases where you don't know the type of a value you are passing into a function but would like to get rid of the `any` cases. This increases the safety of your code, as the `any` type can propagate, making your codebase more prone to errors.

<br>

### `strictNullChecks`

In TypeScript, `null` and `undefined` are assignable to every type, meaning that they are in the domain of all types.

```ts
let num: number = 123;
num = null; // Okay
num = undefined; // Okay
```

Oftentimes, this can lead to unexpected errors, as you can call methods on a variable whose value is `null` or `undefined`.


```ts
interface Person {
  hello(): void;
}

const num: number = undefined;
const str: string = null;
const person: Person = null;

person.hello(); // 🔴 Runtime Error!
```

In strict null checking mode, `null` and `undefined` do not automatically belong to all types, and therefore you can't use them for a type that doesn't include `null` or `undefined`. This way, you can get an error at compile time that says `Object is possibly 'undefined'`.


`Luna` is an instance-object of `Dog`.

```ts
class Dog
{
    age: number
    breed: string    
    
    constructor(age: number, breed: string) 
    {
        this.age = age
        this.breed = string
    }    
    
    getRelativeAge(): number
    {
        return this.age * 7
    }
}

let Luna = new Dog(2, 'Labrador')
```

This syntax is equivalent to using function-objects in JavaScript ES5.

```ts
function Dog(age, breed)
{
    this.age = age
    this.breed = breed
}

Dog.prototype.getRelativeAge = function() {
    return this.age * 7
}

var Spot = new Dog(2, 'Labrador')
```

### Inheritance

Now that you know how to create objects, it's important to learn about inheritance in TypeScript. Inheritance allows subclasses to inherit certain attributes from its parent class.

For example, you have `Animal`, as a parent class.

```ts
class Animal
{
    age: number
    breed: string    
    
    constructor(age: number, breed: string)
    { 
        this.age = age
        this.breed = breed
    }    
    
    makeSound_(sound: string): void
    {
        console.log(sound)
        console.log(sound)
        console.log(sound)
    }
}
```

Then, you can create a `Dog` subclass. You can implement basic inheritance using the `super` keyword, which is used as a function in the subclass to call the corresponding parent function.


```ts
class Dog extends Animal
{
    playsFetch: boolean    constructor(age: number, breed: string, playsFetch: boolean)
    {
         super(age, breed) // call parent constructor
         this.playsFetch = playsFetch
    }    makeSound(): void
    {
        super.makeSound_('woof woof')
    }    getAgeInHumanYears(): number
    {
        return this.age * 7    // super.age will throw error
    }
}
class Cat extends Animal
{
    constructor(age: number, breed: string)
    {
        super(age, breed)
    }    makeSound(): void
    {
        super.makeSound_('meow meow')
    }
}
```

### Interfaces

Interfaces are powerful in JavaScript (and TypeScript), because they have zero runtime impact. TypeScript allows you to declare the structure of the variables, which gives you even more power. 


```ts
interface Point {
    x: number; y: number;
}
declare var test: Point;
```

Interfaces in TypeScript are open-ended, so another author can build upon the existing declaration of the `test` variable.

```ts
interface Point {
    x: number; y: number;
}
declare var myPoint: Point;

interface Point {
    z: number;
}

var myPoint.z; // Allowed
```

Classes can also implement interfaces so that they follow a pre-defined object structure by using the `implements` keyword.

```ts
interface Point {
    x: number; y: number;
}

class MyPoint implements Point {
    x: number; y: number; // Same as Point
}
```

Because of this `implements` keyword, any changes in the interface will create a compilation error so that you can easily update your codebase.

```ts
interface Point {
    x: number; y: number;
    z: number; // New member
}

class MyPoint implements Point { // ERROR : missing member `z`
    x: number; y: number;
}
```

## Types in TypeScript

One of the most integral aspects of TypeScript is creating custom types from existing generic types. 

### Union type

Oftentimes, you may want your code to allow more than one data type. This need is especially true when accepting a `null` or `undefined` value. The **union type** can solve this problem, which is denoted by the `|` annotation.

```ts
const hello = (name: string | undefined) => { /* ... */ };
```

In this example, the type `name` is defined as `string | undefined`, meaning that any variable of type `name` can either be a `string` or `undefined`.

### Intersection type

An intersection type combines multiple types into one, such that the new type has the features of the combined types. You can do this through the `extend` keyword, as seen below.

```ts
function extend<T, U>(first: T, second: U): T & U {
  return { ...first, ...second };
}

const x = extend({ a: "hello" }, { b: 42 });

// x now has both `a` and `b`
const a = x.a;
const b = x.b;
```

### Tuple type

Unlike JavaScript, TypeScript offers [Tuple types](https://www.educative.io/edpresso/arrays-vs-tuples-in-typescript), which allow you to express an array with non-uniform types and a fixed number of elements. A tuple is demonstrated in the below example.


```ts
var nameNumber: [string, number];

// Okay
nameNumber = ['Ben', 12345];

// Error
nameNumber = ['Ben', '12345'];
```

<br>

### Other topics to learn

There's much more to learn to be a true master of TypeScript. Take a look at this list to see what lies ahead.

- Mapped types

- Discriminated union types

- Decorators

- Function types and return types

- Functional programming in TypeScript

- State machines

- Generic functions

<br>

## Wrapping up and Resources 

Now that you have been introduced to some more advanced topics in TypeScript, it's time to begin exploring even more of the powerful TypeScript features. Check our [Advanced TypeScript Masterclass](https://www.educative.io/courses/advanced-typescript-masterclass) to master the language and fully utilize the tools offered by TypeScript.

After finishing the course, you will feel more confident in your TypeScript skills, being able to write your own types, easily identify errors after compiling, and even improving your overall JavaScript knowledge. The topics that will be covered are strict types, generic functions, generic interfaces, composing types, common errors, and more.

<br>

### Continue reading about TypeScript

- [TypeScript Tutorial: A step-by-step guide to learn TypeScript](https://www.educative.io/blog/typescript-tutorial): Follow a roadmap to understand the basic concepts in TypeScript

- [React and TypeScript](https://www.educative.io/blog/react-and-typescript): Learn how to utilize with TypeScript and React to develop powerful web applications.