# Mastering TypeScript Fundamentals

### What is typescript?

TypeScript is a programming language that builds upon JavaScript and brings additional features. It introduces static type checking, which means it checks the types of values you're using in your code to catch mistakes early on. As you write your code, TypeScript analyzes it in real time, providing feedback and ensuring you use the correct types effectively. It's like having a helpful friend who analyzes your code as you type, making your coding experience easier and more organized.

### Types in typescript

TypeScript has a variety of built-in types that you can use to define your variables. Here are some of the most common ones:

* `number`: represents numeric values like 42 or 3.14
    
* `string`: represents text values like "Hello, world!" or "42"
    
* `boolean`: represents boolean values `true` or `false`
    
* `null` and `undefined`: represents the absence of a value
    
* `object`: represents any object type, including arrays and functions
    
* `any`: represents any type, and can be used when you don't know the type of a variable ahead of time
    
* `void`: represents the absence of a value, typically used as a return type for functions that don't return anything
    

In addition to these basic types, TypeScript also supports more advanced types like union types, intersection types, and generics. But more on these later.

**Syntax**: `let variableName: type = value`

```typescript
let num: number = 67
```

### Type Inference

Type inference in TypeScript is like having a clever assistant who can automatically guess and figure out the types of values in your code based on how you use them. It saves you from explicitly declaring types every time, making your code more concise and readable. With type inference, TypeScript analyzes your code and infers the types behind the scenes, making programming faster and more intuitive.

eg: `let num = 7`

The type of num will automatically be inferred as a number.

> In case ts is not able to infer the type, it will set it as `any`.
> 
> To prevent the above scenario from happening we can use `noImplicitAny` in our config file. As `any` isn't type-checked, we should avoid using it.

### Defining Functions

Defining parameter types:

`cont funcName = ( var1: type, var2: type) => {}`

Defining return type:

`cont funcName = (): type => {}`

Example: A function taking in the date and returning the number of days from that date

```typescript
const getDaysFromDate = (date: Date): number => {
  const today: Date = new Date();
  const timeDifference: number = today.getTime() - date.getTime();
  const daysDifference: number = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
  return daysDifference;
}
```

### Type Alias

A type alias in TypeScript is like giving a nickname to a specific type. It allows you to create a custom name for a type, making your code more expressive and readable. Instead of repeatedly using complex or lengthy type annotations, you can define a type alias once and then use that alias throughout your code.

Eg: you can create a type alias, `userD`, which you can use anywhere you want to perform any operation on the user.

```typescript
type UserD = {
    name: string;
    age: number;
}

const updateUser = (user: UserD) => {
    // some code
}
```

**Readonly**

The `readonly` modifier in TypeScript is used to indicate that a property of a type can only be read and cannot be modified. It ensures that once a property is assigned a value, it cannot be changed later.

```typescript
type UserD = {
    readonly _id: string;
    name: string;
}
```

Typescript will throw an error if we try to change the value of the \_id.

> Combining types
> 
> `type A = { name: string }`
> 
> `type B = A & { isPro: boolean }`
> 
> now B becomes: `{ name: string; isPro: boolean }`

### Defining Arrays

**type\[\] and Array&lt;type&gt;**

These are functionally equivalent and can be used interchangeably. The choice between them often comes down to personal preference or the existing coding style within a project.

`const arrName: type[] = []`

`const arrName: Array<type> = []`

**Specifying length:**

We can specify the length an array is supposed to be, if you try to add or remove values from the array, TypeScript will give you an error because it doesn't match the defined length.

`const arrName: Array<type, length> = []`

**ReadonlyArray:**

`ReadonlyArray` type is a built-in utility type that represents an immutable array. It ensures that the array cannot be modified once it is created, preventing any additions, removals, or modifications to its elements.

The `ReadonlyArray` type is useful when you want to create arrays that should remain constant and not be modified inadvertently.

`const arrName: ReadonlyArray<type> = []`

A good use case of type aliases can be defining a type of userD for an array of users.

```typescript
type UserD = {
    id: number;
    name: string;
    age: number;
}

const users: UserD[] = [
    {id: 1, name: 'Mario', age: 20},
    {id: 2, name: 'Luigi', age: 23}
]
```

### Unions

A union in TypeScript is like a combination of different types. It allows you to define a type that can be one of several types. For example, you could have a variable that can be either a number or a string. The types are separated by pipe `|` symbol.

`type id = number | string`

`type arr = (boolean | string)[]`

### Tuples

A tuple is an array type that knows exactly how many elements it contains and exactly which types it contains at specific positions.

syntax: `type tupleName = [string, number]`

eg: `let arr: [string, boolean];`

if we define arr like this: `arr = [23, false]` it will throw an error as type of element on index 0 should be a string, not a number.

```typescript
type Person = [string, number, boolean]

const person: Person = ["John Doe", 30, true]
```

### Interface

The interface is the same as the `type alias` but with a few additional features:

1. It can be re-opened i.e., we can redefine the interface with some additional properties. E.g.
    
    ```typescript
     interface UserD { 
        name: string;
        age: number;
     }
    
    interface UserD {
        isPro: boolean;
    }
    ```
    
    Re-opening interface does not override the previous definition. But it adds the new types with the previous ones. So now `UserD` contains name, age and isPro.
    
2. Can extend other interfaces. E.g.
    
    ```typescript
    interface Animal {
      name: string;
      age: number;
      sound(): void;
    }
    
    interface Dog extends Animal {
      breed: string;
      bark(): void;
    }
    ```
    

> Be careful while naming interfaces, as you might be re-opening some interface present in a file of some library that you downloaded.

### Enum

It allows you to define a set of named constants. It helps us define a specific list of options or choices that something can be. For example, if we have a system with three user roles: "Admin", "Moderator", and "User". Instead of using plain strings to represent these roles throughout the code, we can define an enum called "UserRole" with these three members.

```typescript
enum UserRole {
  Admin = "ADMIN",
  Moderator = "MODERATOR",
  User = "USER"
}
```

That concludes this blog, you now possess the essential knowledge to seamlessly incorporate TypeScript into your projects. Best of luck on your path to becoming an exceptional software developer, and may your web creations be nothing short of extraordinary!
