Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS Flow: Is inheritance in Flow broken?

Consider a situation where you have a class B extending from class A. You create an object of type B and call a method fooA defined in A and then a method fooB defined in B.

class A {
  fooA () {
    console.log('fooA called')
    return this
  }
}

class B extends A {
  fooB () {
    console.log('fooB called')
    return this
  }
}

new B().fooA().fooB()

When run, the code logs the following as expected

fooA called
fooB called

So Javascript understands that new B().fooA() is an object of class B. However Flow gives me the following error message:

Cannot call new B().fooA().fooB because property fooB is missing in A

What to do? I'm interested in a solution where I do not need to change the parent class A because it is defined in an npm package. I can change B though.

like image 365
Clemens Avatar asked Nov 07 '22 07:11

Clemens


1 Answers

If you type the fooA method as returning this, then Flow understands that any classes that extend the A class will also return an instance of themselves from the method:

(Try)

class A {
  fooA (): this {
    console.log('fooA called')
    return this
  }
}

class B extends A {
  fooB () {
    console.log('fooB called')
    return this
  }
}

new B().fooA().fooB() // No error

Since you don't want to change the A class: another easy way to get this working is to type the fooA function of B class to return an instance of B:

(Try)

class A {
  fooA () {
    console.log('fooA called')
    return this
  }
}

class B extends A {
  fooB () {
    console.log('fooB called')
    return this
  }
  fooA: () => B; // Hey Flow, this actually returns a B
}

new B().fooA().fooB() // No error!
like image 105
James Kraus Avatar answered Nov 09 '22 22:11

James Kraus