Master Union And Intersection in Typescript

Master Union And Intersection in Typescript

  • #webdev
  • #typescript
  • #beginners
  • #programming
3 min read

In TypeScript, union and intersection types serve as powerful tools to enrich the flexibility and robustness of type definitions.

Table of content:



Union:

Union types allow us to define a variable that can hold values of multiple types. Previously, we could only specify a single type for a variable:

type value = string;

Union types are usefull when a variable needs to handle different types of values, which make type definitions more flexible

type value = string | number;

Consider the following example:

const logMessage = (value): void => {
  if (typeof value === "string")
    console.log(`string parameter = ${value}`);
  else if (typeof value === "number")
    console.log(`number parameter = ${value}`);
};

In logMessage function, the value parameter is accepted without any type definition, which lead an implicit assignment as any type, means it will accept anything.

For example, consider a scenario where we want that value will only accept number or string here in that case we can use union. syntax like value: string | number which mean that it will accept only string or number, if we define like value: string | number it only accept string, number or boolean. Let's apply it in previous example.

const logMessage = (value: string | number): void => {
  if (typeof value === "string")
    return console.log(`string parameter = ${value}`);

  console.log(`number parameter = ${value}`);
};
const logMessage = (value: string | number | boolean): void => {
  if (typeof value === "string")
    return console.log(`string parameter = ${value}`);
  else if (typeof value === "number")
    return console.log(`number parameter = ${value}`);

  console.log(`boolean parameter = ${value}`);
};

Also beside types we can define what value it can contain like for example gender. There are two gender "male" and "female", so if someone give anything else then we don't want to accept it.

type User = {
  id: string;
  name: string;
  age: number;
  gender: string;
};

const user1: User = {
  id: "1",
  name: "John Doe",
  age: 20,
  gender: "male",
};
const user2: User = {
  id: "2",
  name: "Alice Smith",
  age: 22,
  gender: "shorifa", // something else without "male" or female
};

In above example we only want to gender value as "male" or "female" not anything else like "shorif", "shorifa" so we also can mention that what gender can contain like below.

type User = {
  id: string;
  name: string;
  age: number;
  gender: "male" | "female";
};

const user1: User = {
  id: "1",
  name: "John Doe",
  age: 20,
  gender: "male",
};
const user2: User = {
  id: "2",
  name: "Alice Smith",
  age: 22,
  gender: "shorifa", // Error: Type "shorifa" is not assignable to type '"male" | "female"'
};

Now take a look at another example:

interface Developer {
  name: string;
  role: string;
  programmingLanguages: string[];
  experienceYears: number;
}
interface Designer {
  name: string;
  role: string;
  designTools: string[];
  experienceYears: number;
}
type Employee = Developer | Designer;

const employee1: Employee = {
  name: "Bob Johnson",
  role: "Front-end developer",
  programmingLanguages: ["JavaScript", "TypeScript"],
  experienceYears: 5,
};
const employee2: Employee = {
  name: "Alice Smith",
  role: "UI Designer",
  designTools: ["Photoshop", "Figma"],
  experienceYears: 5,
};

In this example, we have two interfaces: Developer and Designer. We want to create a new type called Employee that represents employees who can be either developers or designers. We achieve this using a union type.

Here employee1, employee2 are of type Employee and employee1 is developer and employee2 id designer.

This use of union types demonstrates how TypeScript empowers developer to create versatile and expressive type definitions so easily.


Intersection:

Intersection is denoted by &, I is used to combine multiple interface or types to create new type.

let's understand intersection through an example.

interface FrontendDeveloper {
  id: string;
  name: string;
  frontendSkills: string[];
}
interface BackendDeveloper {
  id: string;
  name: string;
  backendSkills: string[];
}

type FullstackDeveloper = FrontendDeveloper & BackendDeveloper;

const developer1: FullstackDeveloper = {
  id: "1",
  name: "Michael Johnson",
  frontendSkills: ["HTML", "CSS", "JavaScript", "React", "Redux"],
  backendSkills: ["Nodejs", "Express", "Mongodb", "PostgreSQL"],
};

Here in this example we have two interface named FrontendDeveloper, BackendDeveloper, we combined both to create type FullstackDeveloper and after comining them its type will look alike ---

type FullstackDeveloper = {
  id: string;
  name: string;
  frontendSkills: string[];
  backendSkills: string[];
};

where frontendSkills came from FrontendDeveloper and backendSkills came from BackendDeveloper.

Let's see one more example using type instead of interface :

type People = {
  name: string;
  age: number;
};

type Employee = {
  id: string;
  companyName: string;
  salary: number;
  designation: string;
};

type EmployeeFullDetails = People & Employee;

const employee1: EmployeeFullDetails = {
  name: "John Doe",
  age: 30,
  id: "123456",
  companyName: "TechCorp",
  salary: 80000,
  designation: "Senior Software Engineer",
};

Similarly, we define a new type EmployeeFullDetails by intersecting the People and Employee types. This allows EmployeeFullDetails to contain properties from both types, providing a comprehensive representation of an employee's details.


Union and intersection types are valuable features in TypeScript, offering developers powerful tools to create flexible and robust type definitions. By using these features, developers can write more expressive and error-resistant code, leading to improved software quality and developer productivity.

Image description