Наследование потока приводит к несовместимому типу во время выполнения - PullRequest
0 голосов
/ 07 июня 2019

A.js:

// @flow
export interface A {
  propA: string;
  method(): void;
}

B.js:

// @flow
import { A } from "../interfaces/A.js";
export class B implements A {
  propA: string;
  // Additional properties here...

  method() { //do stuff }
  // Additional methods here...
};

main.js:

// @flow
import { A } from "../interfaces/A.js";
import { B } from "../classes/B.js";

export const processA = (w: string, obj: A): string => {
  return processB(w, obj);
};

const processB = (_w: string, _obj: B): string => {
  return _w;
};

Ошибка: Cannot call 'processB' with 'obj' bound to '_obj' because 'A' [1] is incompatible with 'B' [2].

(Да, я знаю, что A / B obj не используются в этих функциях, это просто урезанный пример)

Я понимаю, почему генерируется ошибка, потому что в processB нет гарантии, что вход _obj имеет тип B, поскольку он имеет тип A. Но я хотел бы иметь метод, который принимает obj: A, а затем переходит к подметоду, который требует, чтобы obj был типа B.

Есть ли способ сделать это? Я вроде как взломал его, вручную проверяя constructor.name и используя instanceof перед вызовом processB, и меняя объявление на const processB = (_w: string, _obj: A).

Но, похоже, мог бы быть и лучший способ. Я хочу, чтобы начальный метод принимал любой объект, который реализует интерфейс, а затем имел подметоды, которые заставляют входной объект быть определенным классом, расширяющим этот интерфейс.

1 Ответ

0 голосов
/ 10 июня 2019

Я мог бы подумать только об использовании instanceof, поскольку Flow требуется какой-то способ гарантировать тип obj. Вам не нужно менять processB, чтобы принять A, если вы используете instanceof, однако. Например,

interface A {
  propA: string;
  method(): void;
};

class B implements A {
  propA: string;
  // Additional properties here...
  propB: string;

  method() { 
    // do stuff
  }
  // Additional methods here...
}

class C implements A {
  propA: string;
  // Additional properties here...
  propC: string;

  method() {
    // do stuff
  }
  // Additional methods here...
}

function processA(w: string, obj: A): string {
  if (obj instanceof B) {
    return processB(w, obj);
  } else if (obj instanceof C) {
    return processC(w, obj);
  }

  throw new Error('Unsupported implementation of interface A');
  // or just return a default string
};

function processB(w: string, obj: B): string {
  return w + obj.propB;
};

function processC(w: string, obj: C): string {
  return w + obj.propC;
}

Try Flow

...