流继承在运行时导致类型不兼容

时间:2019-06-06 22:39:56

标签: javascript inheritance types casting flowtype

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)来解决问题。

但是似乎有更好的方法。我希望初始方法接受实现该接口的任何对象,然后具有将输入obj强制为扩展该接口的某个类的子方法。

1 个答案:

答案 0 :(得分:0)

我只能考虑使用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