Learn TypeScript The Right Way Typescript Icon

TypeScript is complex, unless you have all the answers...

TypeScript Literal Type Guards and in Operator

Welcome back to the TypeScript Type Guards series! You’re entering the realms of next level knowledge, woohoo!

For reference, the 4 articles in this TypeScript series:

Enjoying the series? Come and master the whole TypeScript language with us across 2 courses, beginner concepts and finally advanced. Full of real-world examples, it’ll answer so many questions you have and will have. Click here to check out more of what you’ll learn with us!

In this post we are going to learn about Literal Type Guards and then we will learn how to use the in operator.

Table of contents

The in operator

The in operator is very interesting, it gives us the ability to say const exists = and then we could test something.

const exists = 'localStorage' in window;

If we run this in the browser this would result to true for browsers that have this 'localStorage' property on the window object. What it’s essentially saying is does the window object have a property called 'localStorage'. This is different to window.localStorage because this is looking up the value whereas the in window, and we’re checking this 'localStorage' as a string, is checking whether the property even exists. It doesn’t care about the value, the value could be false and this would result to true.

Angular Directives In-Depth eBook Cover

Free eBook

Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.

  • Green Tick Icon Observables and Async Pipe
  • Green Tick Icon Identity Checking and Performance
  • Green Tick Icon Web Components <ng-template> syntax
  • Green Tick Icon <ng-container> and Observable Composition
  • Green Tick Icon Advanced Rendering Patterns
  • Green Tick Icon Setters and Getters for Styles and Class Bindings

This is a brief introduction to the in operator, you’ll also see this with something like a for loop. Dos prop exist in object, if so we want to iterate it with a for loop.

for(const prop in object){}

Now let’s apply this to the code below.

class Song {
  constructor(public title: string, public duration: number) {}
}

class Playlist {
  constructor(public name: string, public songs: Song[]) {}
}

function isSong(item: any): item is Song {
  return item instanceof Song;
}

function getItemName(item: Song | Playlist) {
  if(item instanceof Song) {
    return item.title;
  }
  return item.name;
}

On our isSong() function we could return item. But before doing so we want to check if the title exists in our item. Now the item gets passed through, it could be a Song or it could be a Playlist.

function isSong(item: any): item is Song {
  return 'title' in item;
}

It is important to remember that 'title' in item; returns a boolean of whether the property exists or not. If the item in the title is available then we know that we are dealing with a Song.

Literal Types

In TypeScript we can create Literal Types, this means that the type is in fact a literal. If we did something like const foo = 'bar';, by default this would have a literal type of bar. We could change this by adding a type string const foo: string = 'bar';. So we have changed the type by manually typing this for ourselves.

Let’s now demonstrate this on the code above. If we take our Song class, even though this could be done on a type, object, interface. We are going to say that the kind here is of type 'song'. If we were to hover over this in our IDE we would see Song.kind: "song" so it’s a string literal.

class Song {
  kind: 'song';
  constructor(public title: string, public duration: number) {}
}

Similarly we can say we are having just a 'playlist'.

class Playlist {
  kind: 'playlist';
  constructor(public name: string, public songs: Song[]) {}
}

We can now go ahead and refactor the getItemName function. So instead of saying if it is a song and say if the kind of item equals a 'song'. Everything will be perfectly implied for because we are using structural typing with TypeScript.


function getItemName(item: Song | Playlist) {
  if(item.kind === 'song') {
    return item.title;
  }
  return item.name;
}

We have now learned how to use a literal type and we can use another Type Guard when we use that title and then in the item is our isSong function. The literal type is just another way we can detect a particular property or a type of something and then we can infer that type and that’s the key to remembering: we infer those types inside those conditional blocks such as an if statement.

Related blogs 🚀

Free eBooks:

Angular Directives In-Depth eBook Cover

JavaScript Array Methods eBook Cover

NestJS Build a RESTful CRUD API eBook Cover