DEV Community

loading...

The Power of Union and Type Guard in TypeScript 🤯

Paulo Eduardo Rezende
・3 min read

On the world of TypeScript we have two properties that are smarter than you think, this thing is the Union Types and Type Guards and I'll talk a little bit about the bellow

Union Types

In javascript development, there are a few moments when you will have to deal with two or more types of information in your parameter or variable, that's where the union types comes into play. As the name implies, this guy will perform the theoretical merge of the types we pass to him, to declare a type union, we use the pipe character, as in the example below

// Variable
let myWonderfulVariable: number | string;

// Function
const myFunction = (info: string | number): void => {}
Enter fullscreen mode Exit fullscreen mode

But if you think you just define the types you want and quit using, you're wrong. Under the hood, TypeScript will perform a verification of the types you entered and will make available ONLY the methods that are common among the informed types, let's take the example of its function just above...

Union of common methods performed by TypeScript

The same is true of any interface or type you may have...

Union of common methods performed by TypeScript when using Interface or Type

Type Guards

Directly speaking, we can say that type guards allows you to restrict the type of content to a conditional block, where we can perform these checks using some operators which I will comment below

typeof

It allows you to perform verification according to the primitive types we have, namely: number, string, boolean and symbol

const myFunction = (x: number | string): void => {
  if (typeof x === 'number') {
    console.log('The variable X it\'s like a number')
  }

  if (typeof x === 'string') {
    console.log('The variable X it\'s like a string')
  }
}
Enter fullscreen mode Exit fullscreen mode

But now you may be wondering, why does typeof only work with the primitive values I commented above? Look at this...

types of an array, object and null

When you try to compare something other than a number, string, boolean, or symbol, JavaScript ends up returning it as an object 🙃

instanceof

It allows you to perform a check of any variable that was created through a constructor

class Company {
  companyName: string;
  companyAddress: string;
  location: {
    lat: number;
    lng: number
  }
}

class User {
  userName: string;
  userAddress: string;
  location: {
    lat: number;
    lng: number
  }
}

const myFunction = (x: Company | User): void => {
  if (x instanceof Company) {
    console.log('The variable X it\'s a instance of Company')
  }

  if (x instanceof User) {
    console.log('The variable X it\'s a instance of Company')
  }
}
Enter fullscreen mode Exit fullscreen mode

in

Checks if a property exists in the given context

interface Company {
  companyName: string;
}

interface User {
  userName: string;
}

const myFunction = (x: Company | User): void => {
  if ('companyName' in x) {
    console.log('The `companyName` exists on variable X')
  }

  if ('userName' in x) {
    console.log('The `userName` exists on variable X')
  }
}
Enter fullscreen mode Exit fullscreen mode

References

If you liked the topic and want to dig deeper, I recommend some sources to dig deeper into not only the subject here, but also TypeScript as a whole:


Today's content is based on my journey to learning TypeScript and it's also my first post here 🎉, follow me on twitter (@pauloedurezende ) if you want to give me feedback (they are always welcome 🤗)

Discussion (2)

Collapse
arihantverma profile image
Arihant Verma • Edited

If we have

interface A {
    name: string;
    id: number;
}

interface B {
  uni: string;
  age: number;
}

type ArrType = Array<A | B>

declare var arr;
let arr: ArrType;

arr.map(item => {
     // need to detect if item is of type A or B
})
Enter fullscreen mode Exit fullscreen mode

How can we do this…?

Collapse
crusader4christ profile image
Herman Klushin • Edited
function isA(v): v is A {
  return "name" in v && "id" in v;
}

function isB(v): v is B {
  return "uni" in v && "age" in v;
}
arr.map(item => {
  if(isA(item)) {
    console.log(item.id, item.name);
  }
})
Enter fullscreen mode Exit fullscreen mode