# Everyday types in TypeScript

As we explored in the last [article,](https://blog.wajeshubham.in/introduction-to-typescript) we have learned about TypeScript, why we use it, how it differs from JavaScript, how to install, configure, and run TypeScript, and some basic types in TypeScript.

In this article, we’ll learn in-depth about some of the most common types in TypeScript. They include `object`, `Array`, `Union types`, `enums`, `tuples`, `any` type, `Literal types`, and Type Aliases.

![typescript-1.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643195053682/FX3QVFNMV.png align="left")

## `object` TYPE:

### DEFINITION:

> **An** `object` is a type of all *non-primitive* values (primitive values are undefined, null, booleans, numbers, and strings).

To define an `object` type, we simply list its properties and their types. To understand this, take a look at the following examples mentioned below:

### IMPLICIT TYPE:

Firstly, open VS Code and create an `index.ts` file with the following code:

```typescript
const course = {
  name: "Learn typescript",
  price: 20,
};

console.log(course);
```

As you hover over the course variable, you will see TypeScript has **inferred** the type of that variable.

Even though we haven't explicitly stated that the `course` variable will have `name` and `price` keys, the TypeScript type inference system handles writing these types.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643266544221/9VOceSCjv.png align="left")

Visually, it looks like a JavaScript object. However, if you notice it has `;` at the end of the key-value pair, and the value of the key is nothing but a `type` of that particular key. The `name` key is of type `string` and the `price` key is of type `number`.

You will see autosuggestions from your IDE if you add a `.` after the `course` variable since the IDE is aware of the keys the `course` variable possesses.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643266705336/wo9eC0kNn.png align="left")

The **Compilation error** with a descriptive message will appear if you attempt to access the key that does not exist in the course object. This is unlike JavaScript, which ignores the error without warning.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643266803807/thGQz78Oz.png align="left")

### EXPLICIT TYPE:

Instead of having TypeScript infer the type for us, let's explicitly specify what type the `course` variable must have.

```typescript
const course: {
  name: string;
  price: number;
  isPublished: boolean;
} = {
  name: "Learn typescript",
  price: 20,
};

console.log(course.name);
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643267602945/_WPOAH0g1.png align="left")

We have assigned a boolean type with the key name `isPublished` to the `course` variable. Since we explicitly stated that the `course` variable must have `name`, `price`, and `isPublished` properties, TypeScript detects this as a compilation error since we are only passing the `name` and `price`.

Let's say you want to keep the `isPublished` property optional. In that case, you can add a `?` before `:` to make that property **optional** as follows:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643267834183/A8B0WwV_j.png align="left")

Furthermore, if you hover over the `isPublished` key, you will see that TypeScript has inferred its type as `boolean | undefined`. The reason is that `isPublished` is optional, and you may not pass any value to it. When that happens, you will receive an `undefined` value, and for that TypeScript warns you that the value of `isPublished` maybe `undefined`.

> `isPublished` is called an optional property in the above example. In contrast, `boolean| undefined` is a `union type` which we will be exploring at great length in this blog.

### NESTED `object` types:

JavaScript also supports nested objects, which means objects can be nested within objects. Let's take a look at how we assign a type when dealing with such nested objects:

```typescript
const course: {
  name: string;
  price: number;
  isPublished?: boolean;
  student: {
    name: string;
    age: number;
  };
} = {
  name: "Learn typescript",
  price: 20,
  student: {
    name: "John",
    age: 30,
  },
};

console.log(course);
```

In the above example, we have `course` which is an object, inside which we have the `student` key, which itself is another `object` with the `name` and `age` keys.

So now, if you try to access `student`, you will also get autosuggestions for the `student` object which is nested inside the `course` object.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643268711992/lbDXOFemq.png align="left")

Also, typescript knows the type of values that we are getting in all the keys of the `course` variable so it can also suggest possible methods for a particular type of values:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643268804692/fgmD9ZMCX.png align="left")

## `Array` TYPE:

### DEFINITION:

> `Array` refers to a special type of data type that can store multiple values of different types sequentially using a special syntax.

### SHORTHAND SYNTAX `type[]`:

Take a look at the following code:

```typescript
const course = {
  name: "Learn typescript",
  price: 20,
  tags: ["typescript", "javascript"],
};

console.log(course);
```

Now, when you hover over `tags`, you will see that it says `string[]`

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643275604887/dz81bjXfIm.png align="left")

It is a shorthand and widely used syntax when assigning a type to an array. A `string[]` notation implies that the array contains only `string` elements.

Since `"typescript"` and `"javascript"` are `strings`, it infers `tags` key as a `string[]` (array of strings).

### GENERIC SYNTAX `Array<type>`:

Another way to specify a type for an array is to use generic syntax, such as:

```typescript
const course: {
  name: string;
  price: number;
  tags: Array<string>; // this is generic syntax Array<type_of_elements>
} = {
  name: "Learn typescript",
  price: 20,
  tags: ["typescript", "javascript"],
};

console.log(course);
```

Here, we specify that `tags` is an `Array` that contains only `string` type elements.

The `<>` indicates that this is a **Generic type**, and we must specify the type of elements to include in this array. *(We will study Generic types in depth in future blogs)*

The following error will occur if the element type is not provided:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643276116359/1f06evACW.png align="left")

> TypeScript generally infers the type of an array with **shorthand syntax**

### `Array` WITH MIXED TYPES:

What if the array has elements of different types? For instance,

```typescript
const course = {
  name: "Learn typescript",
  price: 20,
  tags: ["typescript", "javascript", 20, 10],
};
```

Hovering over `tags` reveals its type as `(string | number)[]` *(Again,* `string | number` is a union type, which means the array includes elements which can be of type `string` or `number`).

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643276227269/arAjVF7DO.png align="left")

> We need something called **type guards** for handling **union types**. This is a bit advanced, so we will cover it in a later blog post.

### `Array` OF `object`:

The types of objects that should be included in an array can be explicitly specified. This allows us to avoid runtime errors and speed up development.

To understand how to define a type for an array of specific objects, let's take an example:

```typescript
const course1 = {
  name: "Learn typescript",
  price: 20,
  tags: ["typescript", 20, 10],
};

const course2 = {
  name: "Learn javascript",
  price: 20,
  tags: ["javascript", 10],
};

const courses: {
  name: string;
  price: number;
  tags: (string | number)[];
}[] = [course1, course2];

console.log(courses);
```

We have two objects here, `course1` and `course2`, whose type is `{ name: string; price: number; tags: (string | number)[]; }`.

Then we have another variable `courses` that contains a list of these two courses, so let's create an array with each element being of a type `{ name: string; price: number; tags: (string | number)[]; }`

The type is now known, and we know that `courses` should be `Array` of type `{ name: string; price: number; tags: (string | number)[]; }`

Therefore, we assigned `{ name: string; price: number; tags: (string | number)[]; }[]` as the type of `courses` variable.

As shown below, TypeScript will automatically infer the type for you if you don't explicitly mention it:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643277201228/-iWWrOUO9.png align="left")

Because TypeScript knows what type of element the `courses` array has, you will get autosuggestions not only for `courses` but also for each element in the `courses` array when you perform any operation on it.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643277328368/aIktQAZVi.png align="left")

## `tuple` TYPE:

### DEFINITION:

> **A** `tuple` type is a type of `Array` that knows how many elements it contains, as well as the type of elements contained at specific positions.

Here is how we can declare a variable as a tuple:

```typescript
let course: [number, string] = [1, "Typescript"];
```

Here, we are saying that the course is an array of fixed length and must have the first element of type `number` and the second element of the type `string`.

If you try to replace the element at the index `0` which is of type `number` with a `string`, you will get a compilation error because we explicitly specified that the element at the index `0` must be a `number`.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643355601047/QcZMvqc66.png align="left")

### EXCEPTION IN `tuple`:

A `tuple` should indeed be immutable, but it is still possible to `push` an element in it because TypeScript doesn't throw a compilation error when you call the `.push()` method.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643355878121/Wqnv-40eU.png align="left")

However, if you attempt to reassign the variable with a different structure, you will receive the following compilation error:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643355992236/Aqer-o6YZ.png align="left")

When reassigning, you need to follow the same structure as when assigning.

### POSSIBLE USE CASE OF `tuple`:

If you need exactly `x` amount of values in an array, and you know the type of each element at a specific index, then you may want to consider using `tuple` type instead of an `Array` type, for more strictness.

## `enum` TYPE:

### DEFINITION:

> **Enums are one of the few features TypeScript has which is not a type-level extension of JavaScript.**

> **By using enums, we can create sets of constants with names. You can create cases and documentation more easily by using enums.**

### NUMERIC ENUMS:

An enum can be defined using the `enum` keyword. Take a look at the following code:

```typescript
enum Role {
  ADMIN = 1,
  READ_ONLY,
  AUTHOR,
}

const user: {
  name: string;
  age: number;
  role: Role;
} = {
  name: "Max",
  age: 30,
  role: Role.ADMIN,
};
```

We have a `numeric enum` where `ADMIN` is initialized with 1. From that point forward, all of the following members will be auto-incremented. Thus, `Role.ADMIN` has the value 1, `READ_ONLY` has 2, and `AUTHOR` has 3.

Once we define an `enum` type, in the above case its `Role`, we don't need to remember what the value of any particular role is, we can simply access enum variables with their names such as Role.ADMIN or Role.READ\_ONLY or Role.AUTHOR.

You will also get autosuggestions from your IDE to do so as follows:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643357300269/WX5Y5MrV8.png align="left")

In addition, if you want to change values for the enum variable, you can do it in your `enum` type `Role`. You don't have to make that change everywhere in the code.

### STRING ENUMS:

In the same way as `numeric enums`, enums can have strings as values. Here's an example:

```typescript
enum Role {
  ADMIN = "admin",
  READ_ONLY = "read_only",
  AUTHOR = "author",
}
```

As the logic remains the same, but in `numeric enums` you will get `1` in return from `Role.ADMIN`, as in `string enums` you will get `"admin"`.

It is up to you what you want to assign to each enum.

### HETEROGENEOUS ENUMS:

Similarly, you can assign mixed types of values to enums as follows:

```ts
enum Role {
  ADMIN = 1
  READ_ONLY = "read_only",
  AUTHOR = 3,
}
```

You get the point!

## `any` TYPE:

### DEFINITION:

> **When a value is of type** `any`, you can access any property of it, call it like a `function`, assign it to a value of any type, or pretty much anything else as long as it's syntactically legal.

### WHY NOT USE `any`:

While `any` type is flexible, it loses all the advantages that TypeScript offers. As a result, it provides the same experience as vanilla JavaScript, thus eliminating the need for TypeScript.

Take a look at the following code:

```ts
let person: any = {
  name: "John",
  age: 30,
};

console.log(person.canWalk())
```

In the above example, we are calling the `canWalk()` function, which does not exist in the `person` variable. However, TypeScript is simply ignoring everything about that particular variable, so we aren't getting any compilation errors.

There is no autocompletion for this variable, which is another downside.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643367817721/cIrRYxxdk.png align="left")

This is a disadvantage of using `any` type and you should avoid using `any` unless you don't know the type of the variable or parameter.

### USE CASE OF `any`:

* When there are no other options, and no type definitions are available for the piece of code you're working on, choose the `any` type.
    
* `any` has some practical use cases. For example, if you are getting a response from an API call and you don't know the structure of the response, then you can use `any` to disable the type-checking for the response object.
    
* **However, if you know the type, be explicit about it**.
    

## UNION TYPES:

### DEFINITION:

> **TypeScript’s type system allows you to build new types out of existing ones using a large variety of operators. We can create new custom types by combining some of the core types.**

### SYNTAX:

The `|` operator enables us to combine different types and create a new one. In the previous topics, we used this concept:

```typescript
let strOrNumArray: (string | number)[] = [];
```

In the above example, we are saying that the `strOrNumArray` could contain elements of type either `string` or `number`

So, you won't get a compilation error if you insert elements of type 'number' or 'string'. However, adding a `boolean` type will result in the compilation error as follows:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643373875571/X31ZYfRB7.png align="left")

The above code can be made valid by adding another type `boolean` after `string` and `number` to make an array that has the possibility of `string`, `number`, and `boolean`, as follows:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643374129901/ZZb5UCxxw.png align="left")

### HANDLE COMPILATION ERRORS USING TYPE GUARDS:

When you use union types, you will get a compilation error if the operation is only valid for one of the types you specified.

Let's see an example to understand this. take a look at the following code:

```typescript
const combineStrOrNum = (param1: string | number, param2: string | number) => {
  let result = param1 + param2; // compilation error here
  return result;
};
```

In the above example, by stating that the `param1` and `param2` are both of type `string | number`, we mean that there may be cases when you pass `param1` as `number` and `param2` as `string`, and as we saw in our blog on Introduction to TypeScript, using `+` between types `string` and `number` can lead to unexpected behavior.

So, typescript complains that this expression can yield unexpected value.

We can handle this with type guards, which are available in JavaScript as well. Look at the following code:

```typescript
const combineStrOrNum = (param1: string | number, param2: string | number) => {
  if (typeof param1 === "number" && typeof param2 === "number") {
    console.log(param1 + param2); // return sum of 2 numbers
  } else if (typeof param1 === "string" && typeof param2 === "string") {
    console.log(param1 + " " + param2); // return concatenation of 2 strings
  } else {
    console.log("Mixed types can not be added"); // return error message
  }
};

combineStrOrNum("Hello", "World"); // Hello World
combineStrOrNum(1, 2); // 3
combineStrOrNum("Hello", 2); // "Mixed types can not be added" (unexpected behavior)
```

Here, the `typeof` keyword indicates the type of a particular variable value.

When the type of `param1` and `param2` is `string`, then only we want to concatenate them with a space.

And if `param1` and `param2` are both numerical, we want to add both of them.

Shortly, we are adding some kind of `type guard` to prevent unexpected behavior.

> In future blogs, we'll explore in-depth concepts about **type guards** and other type guards beside `typeof`.

## LITERAL TYPES:

### DEFINITION:

> **A literal type is a more concrete sub-type of a union type. The difference is that in union types, we specify the types of variables we are expecting, but in Literal types, we specify the exact value we are expecting.**

Let's look at the example to understand this:

### SYNTAX

```typescript
let readOnly: "readonly" = "readonly";
```

Specifically, we are declaring that you can only assign the `"readonly"` string to the `readOnly` variable. A string other than `"readonly"` cannot be assigned to this variable. If you do so, you will get a compilation error as follows:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643395051458/GzXMHcQEY.png align="left")

### USECASE AND IDE SUPPORT:

If you want to accept only predefined values, you can assign a `literal type`. For example:

```typescript
let button: {
  label: string;
  severity: "primary" | "secondary" | "danger" | "warning";
  isSubmit: boolean;
} = {
  label: "Submit",
  severity: "primary",
  isSubmit: true,
};
```

Using the example above, we are creating a `button` variable that has `label` - `string`, `isSubmit` - `boolean`, and `severity` - `"primary" | "secondary" | "danger" | "warning"`.

You will get the following compilation error if you try to assign a different string to the `severity` key, even if it is of type `string`.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643635468436/IVFmEomyH.png align="left")

A benefit of the Literal type is that you get autosuggestions for that particular key with all the possible values.

Take a look at the following image:

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1643635253462/K03WYmRsi.png align="left")

This is useful in large applications when you don't know which value a given variable can have.

## TYPE ALIASES:

### WHAT IS IT?:

We might need to use longer types when working with `union types` or `literal types`. If we want to add another component apart from the `button`, let's say an `alertBar` that is also having the severity of `"primary" | "secondary" | "danger" | "warning"`, it's a bit cumbersome to write it again and again. We can avoid this by using `type aliases`.

### WHY AND HOW TO USE IT?:

Creating dynamic and reusable code is crucial. Don't-Repeat-Yourself (DRY) is an important principle to follow when writing TypeScript code. You can accomplish this using TypeScript aliases.

A custom type can be created by using the `type` keyword followed by the type's name. Let's look at the example below:

```typescript
type SeverityType = "primary" | "secondary" | "danger" | "warning";

let button: {
  label: string;
  severity: SeverityType;
  isSubmit: boolean;
} = {
  label: "Submit",
  severity: "primary",
  isSubmit: true,
};

let alertBar: {
  message: string;
  severity: SeverityType;
  duration: number;
} = {
  message: "This is an error message",
  severity: "danger",
  duration: 2000,
};
```

By creating a `type`, you can now use `SeverityType` anywhere in your code as if it were a `number`, `string`, `boolean`, or any of the primitive or reference types. It's a valid type for TypeScript.

### TYPE OF AN OBJECT:

`type` can also represent the structure of an object, such as what fields it should contain.

Creating a custom type for an object is as easy as using the `type` keyword followed by the type's name and specifying the fields of the type, as well as their types, in the `{}`.

In the above example, we can create the following custom types for `button` and `alertBar`:

```typescript
type SeverityType = "primary" | "secondary" | "danger" | "warning";

type Button = {
  label: string;
  severity: SeverityType;
  isSubmit: boolean;
};

type AlertBar = {
  message: string;
  severity: SeverityType;
  duration: number;
};

let button: Button = {
  label: "Submit",
  severity: "primary",
  isSubmit: true,
};

let alertBar: AlertBar = {
  message: "This is an error message",
  severity: "danger",
  duration: 2000,
};
```

We've created two new types in the above code: `Button` and `AlertBar`, which are type aliases for `button` and `alertBar`, respectively. Now, we can use those types anywhere in our code without having to rewrite them each time.

> We will use `interfaces` instead of types to describe an object's structure in future blogs.

## CONCLUSION:

* In this blog, we've covered some of the most common types of values you’ll find in TypeScript code.
    
* Types can also be found in many places other than just type annotations. We reviewed the most basic and common types you might encounter when writing TypeScript code. These are the core building blocks of more complex types, which will be discussed in future blogs.
    

Make sure to subscribe to our newsletter on [https://blog.wajeshubham.in/](https://blog.wajeshubham.in/) and never miss any upcoming articles related to TypeScript and programming just like this one.

I hope this post will help you in your journey. Keep learning!

My [Website](https://wajeshubham.in), connect with me on [LinkedIn](https://www.linkedin.com/in/shubham-waje/) and [GitHub](https://github.com/wajeshubham).
