How Extract type from union by its field type

How to Extract a Type from a Union by its Field Type in TypeScript

When working with TypeScript, you may come across a situation where you have a union type and you need to extract a specific type from it based on the type of one of its fields. In this blog post, we will explore different solutions to this problem.

Solution 1: Using a Type Guard

One way to extract a type from a union by its field type is by using a type guard. A type guard is a function that returns a boolean value indicating whether a value is of a specific type. In our case, we can create a type guard that checks if the field type matches the desired type and then use it to filter the union.


type Person = { name: string; age: number };
type Animal = { name: string; legs: number };
type Union = Person | Animal;

function isPerson(obj: Union): obj is Person {
  return 'age' in obj;
}

function extractPersonFromUnion(union: Union): Person | null {
  if (isPerson(union)) {
    return union;
  }
  return null;
}

// Usage
const union1: Union = { name: 'John', age: 25 };
const person1 = extractPersonFromUnion(union1);
console.log(person1); // { name: 'John', age: 25 }

const union2: Union = { name: 'Max', legs: 4 };
const person2 = extractPersonFromUnion(union2);
console.log(person2); // null

Solution 2: Using Discriminated Unions

Another approach is to use discriminated unions. A discriminated union is a union type that has a common field, known as a discriminant, which allows TypeScript to narrow down the possible types in the union based on the value of the discriminant field. By leveraging discriminated unions, we can easily extract a type from the union by its field type.


type Person = { type: 'person'; name: string; age: number };
type Animal = { type: 'animal'; name: string; legs: number };
type Union = Person | Animal;

function extractPersonFromUnion(union: Union): Person | null {
  if (union.type === 'person') {
    return union;
  }
  return null;
}

// Usage
const union1: Union = { type: 'person', name: 'John', age: 25 };
const person1 = extractPersonFromUnion(union1);
console.log(person1); // { type: 'person', name: 'John', age: 25 }

const union2: Union = { type: 'animal', name: 'Max', legs: 4 };
const person2 = extractPersonFromUnion(union2);
console.log(person2); // null

Solution 3: Using Conditional Types

If you are using TypeScript 2.8 or later, you can also utilize conditional types to extract a type from a union by its field type. Conditional types allow you to perform type transformations based on conditions.


type Person = { name: string; age: number };
type Animal = { name: string; legs: number };
type Union = Person | Animal;

type ExtractTypeFromUnion = T extends { type: U } ? T : never;

function extractPersonFromUnion(union: T): ExtractTypeFromUnion | null {
  if ('age' in union) {
    return union;
  }
  return null;
}

// Usage
const union1: Union = { name: 'John', age: 25 };
const person1 = extractPersonFromUnion(union1);
console.log(person1); // { name: 'John', age: 25 }

const union2: Union = { name: 'Max', legs: 4 };
const person2 = extractPersonFromUnion(union2);
console.log(person2); // null

These are three different solutions to extract a type from a union by its field type in TypeScript. Choose the one that best suits your needs and enjoy the power of TypeScript’s type system!

Happy coding!


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *