ts中如何写子类的静态方法

class Base {
  public foo:string
  constructor(arg:string){
    this.foo = arg
  }
  static create(arg:string){
    return new Base(arg)
  }
}

class Sub extends Base {
  public bar:number
  constructor(arg:number){
    super("1")
    this.bar = arg
  }
  // 解决方案1
  // 重写 create
  // 报错:不能将类型“string”分配给类型“number”。 因为父类的create 的arg参数是string类型 而子类的 create 的arg参数是number类型
  // static create(arg:number){
  //   return new Sub(arg)
  // }

   // 解决方案2
  // 写一个新的方法
  // 问题: Sub.create() 依然是会编译器被提示 且可以调用 但是事实上不应该通过Sub调用create的方法
  static createBar(arg:number){
    return new Sub(arg)
  }
}
阅读 3.5k
2 个回答

当前最新版本的 TS 编译器不支持。

要变通的话,extends “扩展” 是不行了,只能 implements “实现”。

class Sub implements Base {
    public foo: string;
    public bar: number;

    constructor(arg: number) {
        this.foo = arg + '';
        this.bar = arg;
    }

    static create(arg: number) {
        return new Sub(arg);
    }
}

不过这么写就恶心了,父类里的成员还得重写一遍;要么你就 @ts-ignore 掉;或者 any 大法

P.S. 静态方法覆写报错的问题从 2015 年就有人提出了(GitHub 讨论传送门:https://github.com/microsoft/...),之所以不支持,是出于兼容很多 Polyfill 库的考虑。社区的主流意见是希望增加一个编译器参数可以控制是否允许覆写静态方法,不过到目前为止这个功能都还是没有的 ……

从面向对象的逻辑来说你的出发点就有问题,子类都跟父类不兼容,你还怎么继承?要么你换一个父类去继承,要么你做个兼容:

static create(arg: number | string) {
    ...
    如果 arg 是 string 类型,则转换成 number
    ...
    return new Sub(arg)
}

不过你构造器也表明了这两个类很难称的上有啥继承关系,你可能要再考虑一下你这个设计。

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