DEV Community

Cover image for Understanding Basic Types in TypeScript
Ashutosh Bhadauriya
Ashutosh Bhadauriya

Posted on • Originally published at ashutoshbhadauriya.com

Understanding Basic Types in TypeScript

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.

let isActive: boolean = true;
Enter fullscreen mode Exit fullscreen mode

Number

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

let age: number = 25;
let weight: number = 68.5;
Enter fullscreen mode Exit fullscreen mode

String

The string type represents text values.

let name: string = "John Doe";
Enter fullscreen mode Exit fullscreen mode

Array

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

let numbers: number[] = [1, 2, 3];
let names: Array<string> = ["Alice", "Bob", "Carol"];
Enter fullscreen mode Exit fullscreen mode

Tuple

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

let person: [string, number] = ["John Doe", 25];
Enter fullscreen mode Exit fullscreen mode

Enum

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

enum Color {
  Red,
  Green,
  Blue,
}
let color: Color = Color.Red;
Enter fullscreen mode Exit fullscreen mode

Any

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

let unknownValue: any = 4;
unknownValue = "A string";
unknownValue = true;
Enter fullscreen mode Exit fullscreen mode

Void

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

function logMessage(message: string): void {
  console.log(message);
}
Enter fullscreen mode Exit fullscreen mode

Null and Undefined

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

let empty: null = null;
let notDefined: undefined = undefined;
Enter fullscreen mode Exit fullscreen mode

Never

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

function throwError(message: string): never {
  throw new Error(message);
}
Enter fullscreen mode Exit fullscreen mode

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.

let inferredString = "Hello, World!"; // TypeScript infers the type 'string'
let inferredNumber = 42; // TypeScript infers the type 'number'
Enter fullscreen mode Exit fullscreen mode

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.

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

function add(a: number, b: number): number {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

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

type Age = number;
let personAge: Age = 30;
Enter fullscreen mode Exit fullscreen mode

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

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

let point: Point = {
  x: 5,
  y: 10,
};
Enter fullscreen mode Exit fullscreen mode

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.

type StringOrNumber = string | number;

let inputValue: StringOrNumber = "TypeScript";
inputValue = 42;
Enter fullscreen mode Exit fullscreen mode

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.

type StringOrNumber = string | number;

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

printValue("Hello, World!");
printValue(42);
Enter fullscreen mode Exit fullscreen mode

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.

type A = {
  a: string;
};

type B = {
  b: string;
};

type C = A & B;

let objectC: C = {
  a: "Hello",
  b: "World",
};
Enter fullscreen mode Exit fullscreen mode

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 👋

Top comments (0)