Conditional guard in Typescript

Issue

Im looking into making a typeguard for following case:

interface User {
  email: string | null;
  name: string | null;
  isAdmin: boolean;
}

interface Parent extends User {
  isAdmin: true;
}

interface Child extends User {
  isAdmin: false;
  parent: string | null;
}

const isAdmin = (user: User): user is Parent => user.isAdmin;

Creating a guard in the following way makes it so that the user gets cast to Parent if true but to User if false. How would it be possible to yield Child type if the guard returns false?

Solution

It looks like what you want is a discriminated union type; all users are either parents or children.

interface UserCommon {
  email: string | null;
  name: string | null;
  isAdmin: boolean;
}

interface Parent extends UserCommon {
  isAdmin: true;
}

interface Child extends UserCommon {
  isAdmin: false;
  parent: string | null;
}

type User = Parent | Child

Now you don’t even need to declare a user-defined type guard; just writing if(user.isAdmin) { ... } or if(!user.isAdmin) { ... } is enough to narrow the type of user to Parent or Child respectively.

Answered By – kaya3

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published