【问题标题】:Static factory method in abstract class抽象类中的静态工厂方法
【发布时间】:2018-03-29 23:42:21
【问题描述】:

我正在使用 Typescript 构建一个类系统。有一个主要的抽象类Component,它有一个静态方法create()。这个方法会被孩子调用来构建一个特定的实例

abstract class Component {
    static build() {
       // some additional logic here, for example, cache to reuse instances
       return new this();
    }
}

class Button extends Component { }
class Input extends Component {}

Button.build(); // returns Button instance
Input.build(); // returns Input instance

Same code in TS Playground

这种方法在 Javascript 中运行良好,但 Typescript 在 new this() 行报告错误,说“无法创建抽象类的实例。”

我如何解释 typescript 方法将在派生实例上调用,而不是直接在主抽象类上调用?也许还有其他方法可以实现我需要的 API?

【问题讨论】:

    标签: typescript oop


    【解决方案1】:

    可以在不使用泛型的情况下调用工厂方法。为了在工厂类中使用类型安全,还需要进行一些类型转换。

    下面是两个示例类,一个是抽象类,一个是非抽象类:

    /* eslint-disable prefer-destructuring, max-classes-per-file */
    
    type Class<T> = new (...args: any[]) => T;
    
    class BaseComponent {
      static a = 1;
    
      static build<C extends typeof BaseComponent = typeof BaseComponent>(this: C): InstanceType<C> {
        const a = this.a;
        return new this() as InstanceType<C>;
      }
    }
    
    abstract class AbstractComponent {
      static a = 1;
    
      static build<T extends AbstractComponent = AbstractComponent>(this: Class<T>): T {
        const This = (this as any) as typeof AbstractComponent; AbstractComponent; // To be able to use type safety
        const a = This.a;
        return new this();
      }
    }
    
    class AButton extends AbstractComponent {
      x = 0;
    }
    
    class BButton extends BaseComponent {
      x = 0;
    }
    
    const aButton = AButton.build();
    const bButton = BButton.build();
    
    console.log(aButton.x, bButton.x);
    

    【讨论】:

      【解决方案2】:

      thistypeof Component,由于Component 是抽象类,new this 是不可接受的。即使Component 不是抽象的,Button.build() 返回类型也不会在子类中正确处理。

      它需要一些类型提示,通过generic method:

      abstract class Component {
          static build<T = Component>(this: { new(): T }) {
             return new this();
          }
      }
      
      class Button extends Component { }
      
      const button = Button.build<Button>(); // button: Button
      

      【讨论】:

      猜你喜欢
      • 2011-03-17
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      • 2011-01-05
      • 2014-01-14
      • 2011-09-26
      • 2017-02-08
      • 1970-01-01
      相关资源
      最近更新 更多