【问题标题】:Version of Abstract Methods for Static Methods in TypeScriptTypeScript 中静态方法的抽象方法版本
【发布时间】:2017-02-03 01:08:06
【问题描述】:

我正在使用打字稿创建数据模型范例。我将不同类型的数据存储在不同的地方(SQL、本地缓存)。我想创建一个抽象类,其中包含任何类型的数据存储(创建、查找、更新、计数、销毁)所需的所有方法。通过这种方式,我可以扩展该类并针对不同类型的存储以不同方式实现它,如果我缺少方法,编译器会警告我。然后,我将在描述数据模型的类中扩展其中一个实现。但是,我需要的一些方法(例如 find 和 create)是静态的。我知道打字稿不支持抽象静态方法。是否有类似于我可以使用的抽象方法的东西,以便编译器警告我缺少方法?

我还希望这些静态方法是通用的并且类型与类相同。我知道这对于标准的泛型类没有意义。但是,由于这个类总是会被扩展并且永远不会被实例化,我是否可以在扩展它时键入泛型类,自动更新静态方法上的泛型类型?

【问题讨论】:

    标签: generics inheritance typescript abstract-class


    【解决方案1】:

    我可以使用类似于抽象方法的东西,以便编译器警告我缺少方法

    不是内置的,所以你不会简单地得到好的错误

    // WILL NOT COMPILE. SAMPLE
    class Foo {
        abstract static X() { } 
    }
    
    class Bar extends Foo { // Error here please
    }
    

    但是,您可以使用类型兼容性等技巧来确保:

    interface FooAbstract {
        X(): any;
    }
    let _ensureAbstractMatch: FooAbstract;
    class Foo {
    }
    
    class Bar extends Foo {
    }
    _ensureAbstractMatch = Bar; // Error missing method
    

    示例实现:

    interface FooAbstract {
        X(): any;
    }
    let _ensureAbstractMatch: FooAbstract;
    class Foo {
    }
    
    class Bar extends Foo {
        static X() { }
    }
    _ensureAbstractMatch = Bar; // OKAY
    

    【讨论】:

    • 我认为使用单例模式可能更简单,用方法代替静态方法创建一个通用单例对象,然后使用接口或抽象类键入该通用对象,每个接口或抽象类都有必要的方法目的。您认为这是一个好方法吗?
    • Do you think that is a good approach 如果它有效,那么是的?
    【解决方案2】:

    我知道 typescript 不支持抽象静态方法。有没有类似于我可以使用的 [静态] 抽象方法的东西...?

    还研究抽象静态。答案是abstract static,声明是not yet supported,但你可以做一些接近的事情:要求类对象实现一个抽象类,这相当于说它的静态必须实现接口。以我从其他几个答案1、2、3 中学到的一些部分为例:

    // The static interface.
    abstract class ResourceContainer { 
      abstract create(resource: Creator): Resource
      abstract count(query?: Query): number
      abstract find(query: Query): FindResult
    }
    // The instance interface.
    abstract class Resource { 
      abstract read(): ReadResult
      abstract update(resource: Updator): ReadResult
      abstract delete(): void
    }
    // Attach newable to type corresponding to a concrete class - because Typescript ...
    type NewableResource = ({new (...args: any): any} & ResourceContainer) 
    
    const FooResource: NewableResource = class extends Resource {
      static create(resource: Creator): Resource { console.debug('create'); return new this(); }
      static find(query?: Query) { console.debug('find'); }
      static count(query?: Query) { console.debug('count'); return 0; }
      read() { console.debug('read'); }
      update(resource: Updator) { console.debug('update'); }
      delete() { console.debug('delete'); }
    }
    
    // TODO: flesh out these utility types ..
    type Query = unknown;
    type FindResult = unknown;
    type ReadResult = unknown;
    type Updator = unknown;
    type Creator = unknown;
    
    // Get the *type* of an class object *value*.
    type FooResource = InstanceType<typeof FooResource> 
    
    const x: FooResource = FooResource.create({});
    x.read()
    

    或者,如果您愿意,您可以这样做:

    abstract class Resource {
      static create(resource: Creator): Resource { throw NotImplementedError() }
      static count(query?: Query): number { throw NotImplementedError() }
      static find(query: Query): FindResult { throw NotImplementedError() }
      abstract read(): ReadResult
      abstract update(resource: Updator): ReadResult
      abstract delete(): void
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-03
      • 2014-03-19
      • 1970-01-01
      • 2011-03-19
      • 2012-04-05
      • 2021-10-16
      • 2011-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多