在TypeScript中如何使用没有名称的类引用以在子类中使用不同的静态方法

8
在ES6中,您可以通过this.constructor引用静态方法:
class MainClass {
  static info() {
    return "This is some information";
  }
  constructor() {
    this.info = this.constructor.info(); // Allows subclass to define different '.info()' method.
  }
}

class ChildClass extends MainClass {
  static info() {
    return "This information is from the child";
  }

  constructor() {
    super();
  }
}

在 TypeScript 中有没有一种方法可以做到这一点?我想重写父类的静态方法并从子类中使用它,而不必在实例方法中重新定义引用。目前,我所知道的唯一访问 TypeScript 中静态方法的方式就是使用类名。

MainClass.info();

但是如果我这样做,子类将继续使用MainClass.info();而不是它自己的.info()方法。

2个回答

5
这个怎么样:
interface MainClassConstructor {
    new (): MainClass;
    info(): string;
}

class MainClass {
    static info() {
        return "This is some information";
    }

    private info: string;

    constructor() {
        this.info = (this.constructor as MainClassConstructor).info(); // Allows subclass to define different '.info()' method.
    }
}

class ChildClass extends MainClass {
    static info() {
        return "This information is from the child";
    }

    constructor() {
        super();
    }
}

(playground中的代码)


编辑

您还可以使用typeof MainClass代替我添加的MainClassConstructor接口:

class MainClass {
    static info() {
        return "This is some information";
    }

    private info: string;

    constructor() {
        this.info = (this.constructor as typeof MainClass).info(); // Allows subclass to define different '.info()' method.
    }
}

此外,this.constructor 返回正确类型的讨论/建议在这里:T.constructor should be of type T

另一种选择是使用方法重写:

class MainClass {
    private info: string;

    constructor() {
        this.info = this.getInfo();
    }

    protected getInfo(): string {
        return "This is some information";
    }
}

class ChildClass extends MainClass {
    constructor() {
        super();
    }

    protected getInfo(): string {
        return "This information is from the child";
    }
}

1
使用 as typeof MainClass 是一个很好的补充,可以提供准确的类型支持,而不需要太多额外的代码,感谢您提供了这个。您的第三个代码块没有使用静态方法,但我相信您正在尝试展示@dpoetzsch在评论中建议的重写设置属性之类的东西。是这样吗?(我尝试粘贴游乐场链接,但它太长了无法作为评论) - Shaun
2
在面向对象编程中,通常避免覆盖静态方法,整个静态成员/方法的概念并不是很符合面向对象的思想。在我的最后一个代码块中,我只在父类中设置了一次“info”成员,但它从“getInfo”方法中获取值,然后您可以在子类中重写该方法。我不喜欢在子类中更改父类设置的值,这容易出错。使用此“getInfo”方法,只有一个地方进行赋值。 - Nitzan Tomer

4

看一下这个TypeScript代码:

class MainClass {
  static info() {
    return "This is some information";
  }
  info: string;

  constructor() {
    this.info = (this.constructor as any).info(); // Allows subclass to define different '.info()' method.
  }
}

class ChildClass extends MainClass {
  static info() {
    return "This information is from the child";
  }

  constructor() {
    super();
  }
}

如果编译目标是ES6,那么它将被编译到与上述代码完全相同的代码并正常工作。如果将其编译成ES5也可以正常工作。
请注意,我使用了“as any”技巧来允许调用构造函数上的“.info()”。
或者,您可以在每个子类中覆盖“this.info”的设置。这样就不需要使用这个技巧了。

1
非常好,谢谢。您能提供一个“覆盖this.info设置”的示例吗?这是否以某种方式使用TypeScript的get/set方法?我很少使用它们,所以不熟悉语法。 - Shaun
啊,不,我的意思是在ChildClass构造函数中添加一行代码,如this.info = ChildClass.info(),然后在MainClass中使用this.info = MainClass.info()而不是使用this.constructor的方法。这样做应该也可以(我还没有测试过),并且可能更加可预测。 - dpoetzsch
感谢您提供这个精彩的答案。这真的很有帮助。 - Green Machine Disposer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接