typescript报错Super expression must either be null or a function

absA.ts

import {B} from "./b"
import {C} from "./c"
export abstract class AbsA {
  abstract test(): number
  static list = [
    new B(),
    new C(),
  ]

  static verify(value: number): boolean {
    for(let data of AbsA.list) {
      if (data.test() == value) {
        return true
      }
    }
    return false
  }
}

b.ts

import {AbsA} from "./absA"
export class B extends AbsA {
  test(): number {
    return 88
  }
}

c.ts

import {AbsA} from "./absA"
export class C extends AbsA {
  test(): number {
    return 4545
  }
}

调用

import {AbsA} from "./absA"
const result = AbsA.verify(23234)

报错:

Uncaught (in promise) Error: TypeError: Super expression must either be null or a function
    at _callee$ (index.js?9de7:400:1)
    at tryCatch (runtime.js?96cf:63:1)
    at Generator.invoke [as _invoke] (runtime.js?96cf:294:1)
    at Generator.eval [as throw] (runtime.js?96cf:119:1)
    at asyncGeneratorStep (asyncToGenerator.js?c973:3:1)
    at _throw (asyncToGenerator.js?c973:29:1)

不怎么懂ts,这样怎么改?

阅读 5.8k
1 个回答

初始化 AbsA 的时候需要 BC。而初始化 BC 的时候又需要 AbsA …… 这造成了循环引用。

考虑到正常的设计过程,肯定是先有 AbsA 再有它的子类。而写 AbsA 的时候并不知道有 BC 这两个子类。所以在 AbsA 中不应该引用 BC。然后 AbsA.list 初始化,这个初始化过程一定是在 BC 已经定义之后,要把这个初始化过程后置,一个是在完成子类定义之后修改 AbsA.list 的值,另一个是直接从 AbsA.ts 中导出一个初始化函数,用来在后面初始化。

那么,大概应该这样

  • AbsA.ts 中定义 AbsA,将 AbsA.list 初始化为 []。在 AbsA.ts 中导出一个初始化函数,用来初始化 AbsA.list(由于 JS 的属性开放性,不需要这个初始化函数也可以);
  • 定义 b.tsc.ts,这时候是可以随便使用 AbsA.ts 的,因为那里面没有反过来引用;
  • 这三个文件全部放在 absa 目录中;
  • absa 外面放一个 AbsA.ts,这里进行初始化并导出 AbsABC
import { AbsA, init } from "./absa/AbsA";
import { B } from "./absa/b";
import { C } from "./absa/c";

init([
    new B(),
    new C()
]);

export { AbsA, B, C };

然后外面都使用外层这个 AbsA.ts 就好了

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题