首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在类型记录中使用静态方法访问类类型参数的解决方法

在类型记录中使用静态方法访问类类型参数的解决方法
EN

Stack Overflow用户
提问于 2018-09-26 12:47:31
回答 1查看 12.9K关注 0票数 23

下列错误

静态成员不能引用类类型参数。

从以下代码中得到的结果

代码语言:javascript
复制
abstract class Resource<T> {
    /* static methods */
    public static list: T[] = [];
    public async static fetch(): Promise<T[]> {
        this.list = await service.get();
        return this.list;
    }
    /*  instance methods */ 
    public save(): Promise<T> {
        return service.post(this);
    }
}

class Model extends Resource<Model> {
}

/* this is what I would like, but the because is not allowed because :
"Static members cannot reference class type parameters."
*/

const modelList = await Model.fetch() // inferred type would be Model[]
const availableInstances = Model.list // inferred type would be Model[]
const savedInstance = modelInstance.save() // inferred type would be Model

我认为从这个例子中可以清楚地看到我想要达到的目标。我希望能够调用继承类上的实例和静态方法,并将继承类本身作为推断类型。为了得到我想要的东西,我找到了以下解决办法:

代码语言:javascript
复制
interface Instantiable<T> {
    new (...args: any[]): T;
}
interface ResourceType<T> extends Instantiable<T> {
    list<U extends Resource>(this: ResourceType<U>): U[];
    fetch<U extends Resource>(this: ResourceType<U>): Promise<U[]>;
}

const instanceLists: any = {} // some object that stores list with constructor.name as key

abstract class Resource {
    /* static methods */
    public static list<T extends Resource>(this: ResourceType<T>): T[] {
        const constructorName = this.name;
        return instanceLists[constructorName] // abusing any here, but it works :(
    }
    public async static fetch<T extends Resource>(this: ResourceType<T>): Promise<T[]> {
        const result = await service.get()
        store(result, instanceLists) // some fn that puts it in instanceLists
        return result;
    }
    /*  instance methods */ 
    public save(): Promise<this> {
        return service.post(this);
    }
}
class Model extends Resource {
}
/* now inferred types are correct */
const modelList = await Model.fetch() 
const availableInstances = Model.list 
const savedInstance = modelInstance.save()

我遇到的问题是,覆盖静态方法变得非常乏味。做以下工作:

代码语言:javascript
复制
class Model extends Resource {

    public async static fetch(): Promise<Model[]> {
        return super.fetch();
    } 
}

将导致错误,因为Model不再正确地扩展Resource,因为签名不同。我想不出一种在不给出错误的情况下声明获取方法的方法,更不用说有一种简单直观的过载方法了。

我能做的工作只有以下几点:

代码语言:javascript
复制
class Model extends Resource {
    public async static get(): Promise<Model[]> {
        return super.fetch({ url: 'custom-url?query=params' }) as Promise<Model[]>;
    }
}

在我看来,这不是很好。

是否有一种方法可以覆盖fetch方法,而不必手动转换为Model并使用泛型执行技巧?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-26 14:20:14

你可以这样做:

代码语言:javascript
复制
function Resource<T>() {
  abstract class Resource {
    /* static methods */
    public static list: T[] = [];
    public static async fetch(): Promise<T[]> {
      return null!;
    }
    /*  instance methods */
    public save(): Promise<T> {
      return null!
    }
  }
  return Resource;
}

在上面的Resource中,是一个返回局部声明类的泛型函数。返回的类不是泛型的,因此它的静态属性和方法具有T的具体类型。您可以这样扩展它:

代码语言:javascript
复制
class Model extends Resource<Model>() {
  // overloading should also work
  public static async fetch(): Promise<Model[]> {
    return super.fetch();
  }
}

每件事都有你所期望的类型:

代码语言:javascript
复制
 Model.list; // Model[]
 Model.fetch(); // Promise<Model[]>
 new Model().save(); // Promise<Model>

所以这可能对你有用。

我现在唯一能看到的警告是:

  • class X extends Resource<X>()中有一些不太完美的复制,但我认为您无法获得上下文类型来推断第二个X
  • 本地声明的类型往往不能导出或用作声明,因此您可能需要小心,或者想出解决办法(例如,导出一些结构相同或结构相近的类型,并声明Resource是该类型?)。

希望这能帮上忙。祝好运!

票数 33
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52518125

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档