JS Flow: наследование в Flow нарушено? - PullRequest
0 голосов
/ 09 мая 2018

Рассмотрим ситуацию, когда у вас есть класс B, выходящий из класса A. Вы создаете объект типа B и вызываете метод fooA, определенный в A, а затем метод fooB, определенный в 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()

При запуске код регистрирует следующее, как и ожидалось

fooA called
fooB called

Таким образом, Javascript понимает, что new B().fooA() является объектом класса B. Однако Flow выдает мне следующее сообщение об ошибке:

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

Что делать? Меня интересует решение, в котором мне не нужно менять родительский класс A, поскольку он определен в пакете npm. Я могу изменить B, хотя.

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

Если вы введете метод fooA как возвращающий this, то Flow понимает, что любые классы, которые расширяют класс A, также будут возвращать свой экземпляр из метода:

( Попробуйте )

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

Поскольку вы не хотите изменять класс A, еще один простой способ получить эту работу - ввести функцию fooA класса B для возврата экземпляра B:

( Попробуйте )

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!
0 голосов
/ 09 мая 2018

Функция fooA () возвращает «this», которое является экземпляром «A». Как вы знаете, класс A понятия не имеет, что метод fooB существует. Поэтому Flow (справедливо) указывает на то, что свойство fooB отсутствует в A.

Вы знаете, что на самом деле этот конкретный экземпляр A также является экземпляром B, но Flow не может это сделать. Вы должны сказать ему, что A, возвращаемая функцией fooA (), является экземпляром B в этом конкретном сценарии с использованием приведения.

Изменение вашего звонка на (new B().fooA(): B).fooB() должно устранить ошибку потока.

Javascript (без потока) не заботится об этой семантике. Когда вы вызываете "fooB" для объекта, возвращаемого функцией fooA (), он просто ищет в объекте метод с именем "fooB", который, как оказалось, существует, поэтому он работает, хотя он более склонен к разрыву с помощью рефакторинга. Поток полезен, потому что он заставляет вас оставаться в курсе того, какие типы создаются, и дает вам проверки во время компиляции на наличие этих проблем в будущем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...