Type Manipulation in TypeScript

TypeScript offers strong tools for types manipulation and transformation, these tools allow programmers to create new types by composing, intersecting, unionizing, mapping and conditioning existing ones, in this article we will investigate some of the advanced type-manipulation features in TypeScript including:

Table of Content

  • Intersection Types (&)
  • Union Types (|)
  • Mapped Types
  • Conditional Types

Intersection Types (&)

With intersection types different types can be blended into one unit, these kind of type will hold all properties belonging to intersected types.

Example: In the given below example we are combining Person and Employee Types.

JavaScript
interface Person {
  name: string;
  age: number;
}

interface Employee {
  employeeId: number;
  department: string;
}

type EmployeePerson = Person & Employee;

const pankaj: EmployeePerson = {
  name: "Pankaj Bind",
  age: 20,
  employeeId: 12345,
  department: "Engineering"
};

console.log(pankaj);

Output:

{
name: 'Pankaj Bind',
age: 20,
employeeId: 12345,
department: 'Engineering'
}

Union Types (|)

When you use a union type, you can create a type to be among many types, this indicates that one can choose from any of the assigned types.

Example: In the given below example we are defining Status with Union Types.

JavaScript
type Status = "success" | "error" | "loading";

function printStatus(status: Status) {
  console.log(`The current status is: ${status}`);
}

printStatus("success");
printStatus("error");
printStatus("loading");
// Uncommenting this line will cause an error
// printStatus("complete"); 

Output:

The current status is: success
The current status is: error
The current status is: loading

Mapped Types

When you make mapped types, you make new typed entities by changing what is similar in existing ones, this is helpful if you want to apply one transformation to each property in a type.

Example: In the given below example we are creating a Readonly User Type.

JavaScript
type Readonly<T> = {
  readonly [P in keyof T]: T[P];
};

interface User {
  id: number;
  name: string;
  age: number;
}

type ReadonlyUser = Readonly<User>;

const user: ReadonlyUser = {
  id: 1,
  name: "Pankaj",
  age: 20
};

console.log(user);
 // Uncommenting this line will cause an error
// user.id = 2;

Output:

{ id: 1, name: 'Pankaj', age: 20 }

Conditional Types

Enabling conditional types helps you form types in line with a certain test, this is practical in terms of making types that rely on other types.

Example: In the given below example we are using Conditional Type with Interfaces.

JavaScript
interface Animal {
  live(): void;
}

interface Dog extends Animal {
  bark(): void;
}

type Example1 = Dog extends Animal ? 
                number : string; // number
type Example2 = RegExp extends Animal ?
                number : string; // string

const example1Value: Example1 = 42;
const example2Value: Example2 = "Not an animal";

console.log(example1Value); // 42
console.log(example2Value); // "Not an animal"

Output:

42
Not an animal

Conclusion

TypeScript has strong and flexible type manipulation capabilities, developers can make the code more secure and readable by combining types of intersections, unions, mapped and conditional types, for a complete utilization of the static type system strength in TypeScript, those features have to be employed.



Contact Us