Home > Back-end >  Typescript isn't narrowing variable when using instanceof
Typescript isn't narrowing variable when using instanceof

Time:02-23

I'm trying to understand why TS isn't narrowing inst to just Bar in the example below:

class Foo {}
class Bar { prop = "baz" }

function fn2(inst: Foo | Bar) {
    if (inst instanceof Foo) {
        inst = new Bar()
    }
    inst.prop // prop does not exist on Foo | Bar
}

CodePudding user response:

Typescript is structural, not nominal. So the problem here is that an instance of Bar is assignable to type Foo, so the type guard doesn't actually narrow anything.

class Foo {}
class Bar { prop = "baz" }

const inst: Foo = new Bar() // fine

Playground

An object with one property conforms to the interface of an object with no properties, since all properties (all zero of them) are accounted for.


To make this work, you need to make the two classes have different interfaces.

class Foo { foo = 'foo' }
class Bar { bar = 'bar' }

declare let inst: Foo | Bar

if (inst instanceof Foo) inst = new Bar()
inst.bar // works
inst.foo // error

Playground


Or in your specific case:

class Foo { foo = 'foo' }
class Bar { bar = 'bar' }

function fn2(inst: Foo | Bar) {
    if (inst instanceof Foo) {
        inst = new Bar()
    }
    inst.bar
}

Playground

  • Related