loading...

The Power of Union and Type Guard in TypeScript 🤯

pauloedurezende profile image 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 => {}

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')
  }
}

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')
  }
}

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')
  }
}

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

pic
Editor guide
 

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
})

How can we do this…?