Understanding Basic Types in TypeScript
Tags: webdev, typescript, javascript, react
Published: 2023-05-08 07:11:26

TypeScript, the superset of JavaScript, has been growing in popularity due to its ability to catch errors during compile-time, improve code readability, and simplify refactoring. With TypeScript's type system, you can enhance the code quality while taking advantage of new features. In this blog post, I’ll dive into the basic types in TypeScript, exploring each one in detail.

## The Importance of Types in TypeScript

Types play a significant role in TypeScript, providing type-checking and error-catching at compile-time. By leveraging the power of types, you can catch errors before they even escalate, enhance code readability for team members, and make refactoring a breeze. Let's dive into the basic types in TypeScript and see how they can benefit your projects.

## The Basic Types

Let's get started with the fun stuff. TypeScript’s type inference feature automatically determines a variable's data type. However, it's generally a good idea to declare data types when initializing variables.

We assign data types by simply placing a colon after the variable name but before the equal sign:

`const {variable name}: {variable type} = {variable value}`

This is the convention that most TypeScript data types are declared except for functions and objects.

Some data types come with a bit more complex than that, but you get the general idea.  Below are some brief explanations of data types and examples of how to declare them.

### Boolean

The `boolean` type is used to represent true or false values.

```typescript
let isActive: boolean = true;
```

### Number

In TypeScript, all numeric values are represented by the `number` type, including integers and floating-point values.

```typescript
let age: number = 25;
let weight: number = 68.5;
```

### String

The `string` type represents text values.

```typescript
let name: string = "John Doe";
```

### Array

Arrays are used to store collections of values. TypeScript supports two syntaxes for defining arrays: `Type[]` or `Array<Type>`.

```typescript
let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["Alice", "Bob", "Carol"];
```

### Tuple

Tuples allow you to create an array with a fixed number of elements of known types.

```typescript
let person: [string, number] = ["John Doe", 25];
```

### Enum

Enums provide a way to create user-defined types with a set of named constants.

```typescript
enum Color {
  Red,
  Green,
  Blue,
}
let color: Color = Color.Red;
```

### Any

The `any` type is used when the type is unknown or can change at runtime.

```typescript
let unknownValue: any = 4;
unknownValue = "A string";
unknownValue = true;
```

### Void

The `void` type is typically used as a return type for functions that do not return any value.

```typescript
function logMessage(message: string): void {
  console.log(message);
}
```

### Null and Undefined

Both `null` and `undefined` have their respective types in TypeScript. They are often used as subtypes of other types.

```typescript
let empty: null = null;
let notDefined: undefined = undefined;
```

### Never

The `never` type represents a value that never occurs, typically used for functions that always throw an error or have an infinite loop.

```typescript
function throwError(message: string): never {
  throw new Error(message);
}
```

## Type Inference and Type Annotations

TypeScript has a powerful type inference system that tries to deduce the types of variables and function return values based on their usage. It means that often, you don't need to explicitly specify types, as the compiler can infer them for you.

```typescript
let inferredString = "Hello, World!"; // TypeScript infers the type 'string'
let inferredNumber = 42; // TypeScript infers the type 'number'
```

However, there are cases when the compiler might not be able to infer the correct type or when you want to be more explicit about the types you're using. In such cases, you can use type annotations to explicitly specify the type of a variable or a function's return value.

```typescript
let annotatedString: string = "Hello, World!";
let annotatedNumber: number = 42;

function add(a: number, b: number): number {
  return a + b;
}
```

## Type Aliases and Custom Types

Type aliases provide a way to create custom types by either giving a new name to an existing type or defining a new type using a combination of existing types. This can help improve code readability and maintainability by creating more descriptive types tailored to your application.

### Creating a type alias for an existing type

```typescript
type Age = number;
let personAge: Age = 30;
```

In this example, we create a type alias `Age` for the `number` type, making it more descriptive and specific to our application.

### Defining a new type using a combination of existing types

```typescript
type Point = {
  x: number;
  y: number;
};

let point: Point = {
  x: 5,
  y: 10,
};
```

Here, we create a new custom type called `Point` using an object type with two properties, `x` and `y`. This makes it easier to understand the structure of the object and its purpose in our application.

### Using union types with type aliases

Type aliases can also be combined with union types, allowing you to create a custom type that can hold different values.

```typescript
type StringOrNumber = string | number;

let inputValue: StringOrNumber = "TypeScript";
inputValue = 42;
```

In this example, we create a type alias called `StringOrNumber` that can hold either a `string` or a `number`. This provides flexibility in our application while maintaining type safety

## Union and Intersection Types

Union and intersection types play crucial roles in creating complex type definitions, allowing developers to combine types in flexible and powerful ways.

### Union types

Union types represent a value that can be of one of several types. It is denoted using the `|` symbol between the types.

```typescript
type StringOrNumber = string | number;

function printValue(value: StringOrNumber) {
  console.log(value);
}

printValue("Hello, World!");
printValue(42);
```

In this example, the `StringOrNumber` type is a union type that can be either a `string` or a `number`. The `printValue` function accepts a parameter of this union type, allowing it to handle both strings and numbers.

### Intersection types

Intersection types are used to combine multiple types into one, creating a new type that includes all the properties of the original types. It is denoted using the `&` symbol between the types.

```typescript
type A = {
  a: string;
};

type B = {
  b: string;
};

type C = A & B;

let objectC: C = {
  a: "Hello",
  b: "World",
};
```

In this example, the `C` type is an intersection type that combines the properties of both `A` and `B`. The `objectC` variable must have both `a` and `b` properties, as defined by the intersection type.

## That's a wrap!!

Understanding and utilizing TypeScript's basic types can have a significant impact on the quality of your code. It helps catch errors during compile time, improves code readability, and simplifies refactoring. As you continue to work with TypeScript, you'll discover even more benefits of this powerful language. I encourage you to explore TypeScript further and apply these concepts to your own projects, creating more robust and maintainable codebases. See you in next one 👋