Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

this is type guards resolving to never in else if block

Tags:

typescript

I've below three classes in typescript:

export default abstract class A {
  isB(): this is B {
    return false;
  }
  isC(): this is C {
    return false;
  }
}

export class B extends A {
  isB(): this is B {
    return true;
  }
}

export class C extends A {
  isC(): this is C {
    return true;
  }
}

I've another function that prints the type of a given instance:

export function printType(a: A) {
  if (a.isB()) {
    console.log("B");
  } else if (a.isC()) {
    console.log("C");
  } else {
    console.log("A");
  }
}

If you try and put this code through the typescript compiler, typescript's type narrowing seems to deduce the type of a to be never in the else if block of printType function. Can someone please explain why this happens?

Thanks in advance!

like image 309
Arpit Bhadauria Avatar asked Dec 06 '25 03:12

Arpit Bhadauria


1 Answers

The problem is Typescript uses structural typing. If you don't have any extra fields to differentiate between the classes, no meaningful narrowing could happen and a stays A | never. Just add the difference and the narrowing would work:

Playground

export class B extends A {
    type = 'B';
  isB(): this is B {
    return true;
  }
}

export class C extends A {
    type = 'C';
  isC(): this is C {
    return true;
  }
}
like image 63
Alexander Nenashev Avatar answered Dec 10 '25 19:12

Alexander Nenashev