【问题标题】:Typescript static method in an abstract class to create an instance of self抽象类中的 Typescript 静态方法来创建 self 的实例
【发布时间】:2020-12-30 11:31:46
【问题描述】:

假设我有

abstract class Foo {

}

class Bar1 extends Foo {
    constructor(someVar) { ... }
}

class Bar2 extends Foo {
    constructor(someVar) { ... }
}

我希望能够创建一个静态方法来创建最终类的实例(所有构造函数都具有相同的签名)。所以我想要类似的东西:

abstract class Foo {
    public static someAction(someVar) {
        const self = new this(someVar);
    }
}

但这无法做到,因为Foo 是抽象的。这有可能吗?

更新

如果这些类有自己的模板呢?

abstract class Foo<M> {

}

class Bar1 extends Foo<SomeModel> {...}

现在我想让someAction 知道SomeModel 类型。我试过了

public static someAction<A, T extends Foo<A>>(this: new (someVar: any) => T, someVar: any): T {
    const self = new this(someVar);
    return self;
  }

但是除非我专门做Bar1.someAction&lt;SomeModel&gt;("blah"),否则返回的结果是不可用的数据类型,即Bar1.someAction("blah")不知道数据类型

【问题讨论】:

  • 您有没有找到更新问题的答案?
  • 这正是我遇到的问题

标签: javascript typescript


【解决方案1】:

您可以为静态方法的this 类型添加注解。在这种情况下,this 将引用该类,并且为 this 参数添加注释将使静态方法仅在满足约束的类上可见(在这种情况下,存在具有单个参数的构造函数)并且它还将帮助我们提取调用该方法的类的实际实例类型:

abstract class Foo {
  public static someAction<T extends Foo>(this: new (someVar: any) => T, someVar: any): T {
    const self = new this(someVar);
    return self;
  }
}

class Bar1 extends Foo {

  constructor(someVar: any) {
    super();
  }
}

class Bar2 extends Foo {
  constructor(someVar: any) {
    super();
  }
}
let bar1 = Bar1.someAction(0) // of type Bar1
let bar2 = Bar2.someAction(0) // of type Bar2

【讨论】:

  • 这很好用!我还有一个问题,我会跟进这个问题的更新。如果你也知道,那就太好了!
  • @Titian 在使用泛型扩展类时,我也遇到了 Kousha 在他的更新中提到的问题。类型最终成为基类而不是子类。任何见解将不胜感激!
  • 但是如何从Foo.someAction 访问静态属性。它现在只知道this 是一个构造函数。将 this 声明为 extends typeof Foo 会导致它说抽象类型不可构造。使用交集似乎会导致对构造函数的使用产生很多混淆(我认为是由于如何解析泛型)。
【解决方案2】:

经过一番折腾,我找到了解决泛型问题的方法。

关键是在基类的扩展约束中使用类型变量但是添加带有类型变量的基类作为返回类型的交集。

在此处使用any 而不是T static someAction&lt;A, T extends Foo&lt;any&gt;&gt; 在返回类型上添加&amp; Foo&lt;A&gt;

abstract class Foo<M> {...}

class Bar1 extends Foo<SomeModel> {...}
public static someAction<A, T extends Foo<any>>(
    this: new (someVar: any) => T, someVar: any
): T & Foo<A> {
    return new this(someVar);
}

我在尝试创建用户定义的类型保护时遇到了完全相同的问题,上面的相同技术也解决了这个问题。

public static isThisType<A, T extends Foo<any>>(
    this: new (...args: any) => T, value: unknown
): value is T & Foo<A> {
    return value instanceof this;
}

【讨论】:

    猜你喜欢
    • 2021-01-10
    • 2019-04-15
    • 1970-01-01
    • 2017-02-03
    • 2011-06-07
    • 1970-01-01
    • 2019-04-07
    相关资源
    最近更新 更多