来自 Ruby:如何在 TypeScript 中将静态方法移动到抽象 class?
Coming from Ruby: How to move a static method into abstract class in TypeScript?
我有两个 classes,每个都有一个方法 build
returns 相应 class:
的一个新实例
class Foo {
static build() {
return new Foo();
}
}
class Bar {
static build() {
return new Bar();
}
}
实际的实现比较复杂。但是,我试图通过将实现移至抽象 class 来消除重复,但我不知道如何实现它:
abstract class Base {
static build() {
return // <- ???
}
}
class Foo extends Base {
}
class Bar extends Base {
}
此外,我希望能够在 Foo
和/或 Bar
:
中覆盖 build
class Bar extends Base {
static build() {
instance = super(); // <- couldn't get this working
// do something with instance
return instance;
}
}
也许我的方法完全错误。在 Ruby 中,我会写:
module M
def build
new
end
end
class Foo
extend M
end
class Bar
extend M
end
并覆盖 build
:
class Bar
extend M
def self.build
instance = super
# do something with instance
instance
end
end
我怎样才能在 TypeScript 中实现这些目标?
也许是这样的?
abstract class Base
{
protected static build(cls: {new(): Base}): Base
{
// common init logic comes here
return new cls();
}
}
class Foo extends Base
{
static build(): Foo
{
const instance = Base.build(Foo);
// do something specific with instance
return instance;
}
}
class Bar extends Base
{
static build(): Bar
{
const instance = Base.build(Bar);
// do something specific with instance
return instance;
}
}
const foo = Foo.build();
const bar = Bar.build();
@Amid 的回答很好,只有一个问题是如果 Foo
或 Bar
有它们自己的任何属性,那么您将遇到编译器错误,因为只有 Base.build
returns Base
。你可以引入一个类型参数来解决这个问题:
abstract class Base {
protected static build<T>(cls: { new (): T }): T {
// common init logic comes here
return new cls();
}
}
此外,当将 class 传递给 Base.build
时,您可以只传递 this
,因为静态方法中的 this
将引用当前的 class :
class Foo extends Base {
static build(): Foo {
const instance = Base.build(this); // `instance` will be typed as `Foo` instead of `Base`
// do something specific with instance
return instance;
}
}
[我在这里回答我自己的问题]
查看生成的 JavaScript 后,我意识到在调用超类上的方法时已经传递了 this
。
获得正确的类型要困难得多。这最终对我有用:
interface BaseConstructor<T> {
new(): T;
build(): T;
}
abstract class Base {
static build<T extends Base>(this: BaseConstructor <T>): T {
return new this(); // <- this is either Foo or Bar
}
}
class Foo extends Base {
}
class Bar extends Base {
}
Foo.build(); // instance of Foo
Bar.build(); // instance of Bar
我有两个 classes,每个都有一个方法 build
returns 相应 class:
class Foo {
static build() {
return new Foo();
}
}
class Bar {
static build() {
return new Bar();
}
}
实际的实现比较复杂。但是,我试图通过将实现移至抽象 class 来消除重复,但我不知道如何实现它:
abstract class Base {
static build() {
return // <- ???
}
}
class Foo extends Base {
}
class Bar extends Base {
}
此外,我希望能够在 Foo
和/或 Bar
:
build
class Bar extends Base {
static build() {
instance = super(); // <- couldn't get this working
// do something with instance
return instance;
}
}
也许我的方法完全错误。在 Ruby 中,我会写:
module M
def build
new
end
end
class Foo
extend M
end
class Bar
extend M
end
并覆盖 build
:
class Bar
extend M
def self.build
instance = super
# do something with instance
instance
end
end
我怎样才能在 TypeScript 中实现这些目标?
也许是这样的?
abstract class Base
{
protected static build(cls: {new(): Base}): Base
{
// common init logic comes here
return new cls();
}
}
class Foo extends Base
{
static build(): Foo
{
const instance = Base.build(Foo);
// do something specific with instance
return instance;
}
}
class Bar extends Base
{
static build(): Bar
{
const instance = Base.build(Bar);
// do something specific with instance
return instance;
}
}
const foo = Foo.build();
const bar = Bar.build();
@Amid 的回答很好,只有一个问题是如果 Foo
或 Bar
有它们自己的任何属性,那么您将遇到编译器错误,因为只有 Base.build
returns Base
。你可以引入一个类型参数来解决这个问题:
abstract class Base {
protected static build<T>(cls: { new (): T }): T {
// common init logic comes here
return new cls();
}
}
此外,当将 class 传递给 Base.build
时,您可以只传递 this
,因为静态方法中的 this
将引用当前的 class :
class Foo extends Base {
static build(): Foo {
const instance = Base.build(this); // `instance` will be typed as `Foo` instead of `Base`
// do something specific with instance
return instance;
}
}
[我在这里回答我自己的问题]
查看生成的 JavaScript 后,我意识到在调用超类上的方法时已经传递了 this
。
获得正确的类型要困难得多。这最终对我有用:
interface BaseConstructor<T> {
new(): T;
build(): T;
}
abstract class Base {
static build<T extends Base>(this: BaseConstructor <T>): T {
return new this(); // <- this is either Foo or Bar
}
}
class Foo extends Base {
}
class Bar extends Base {
}
Foo.build(); // instance of Foo
Bar.build(); // instance of Bar