以下错误
静态成员不能引用类类型参数。
以下代码的结果
found
我认为从这个例子中可以很明显地看出我正在努力实现的目标。我希望能够在继承类上调用实例和静态方法,并将继承类本身作为推断的类型。我发现以下解决方法可以得到我想要的东西:
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
我遇到的问题是,重写静态方法变得非常乏味。执行以下操作:
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()
将导致错误,因为签名不同,class Model extends Resource {
public async static fetch(): Promise<Model[]> {
return super.fetch();
}
}
不再正确地扩展Model
。在没有给我错误的情况下,我想不出一种声明获取方法的方法,更不用说有直观的简单重载方法了。
我唯一可以解决的问题是:
Resource
我认为这不是很好。
是否有一种方法可以覆盖fetch方法,而不必手动将其强制转换为Model并用泛型做些技巧?
答案 0 :(得分:3)
您可以执行以下操作:
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
是返回locally declared class的泛型函数。返回的类不是 泛型,因此其静态属性和方法具有T
的具体类型。您可以这样扩展它:
class Model extends Resource<Model>() {
// overloading should also work
public static async fetch(): Promise<Model[]> {
return super.fetch();
}
}
所有内容都具有您期望的类型:
Model.list; // Model[]
Model.fetch(); // Promise<Model[]>
new Model().save(); // Promise<Model>
这样可能对您有用。
我现在可以看到的唯一警告:
class X extends Resource<X>()
中有一些重复项不尽人意,但我认为您不能通过上下文类型来推断第二个X
。
本地声明的类型往往不可导出或用作声明,因此您可能需要在此小心或提出解决方法(例如,导出一些结构上相同或结构上足够接近的类型并声明Resource
是那种类型?)。
无论如何,希望能有所帮助。祝你好运!