我有一个构造函数,并调用static方法来设置一个静态变量。
export abstract class AbstractRepository<T extends Typegoose> {
private static conn: SessionDb<T>; // <-- Compile error here!
protected model: Model<InstanceType<T>, {}>;
constructor(entity: T, collectionName: string){
if(AbstractRepository.conn == null) AbstractRepository.conn = SessionDb.connect(entity);
this.model = AbstractRepository.conn.getModel(collectionName);
}
}
如何键入conn: SessionDb <T>
属性?
这个变量是一个mongoose连接。
保存一个singleton变量以备将来访问有意义吗?
问题
当您有一个泛型类时,泛型参数T
应用于该类的每个实例。创建泛型类的实例时,可以像const myObj = new GenericClass<MyType>(args);
那样指定类型T
,但通常不需要这样做,因为构造函数签名告诉typescript用于创建实例的参数与泛型T
的关系。
通过您的构造函数CCD_ 6,您已经告诉typescript";取变量CCD_ 7的类型并将其用作该实例的通用CCD_;。因此,当您通过调用const myObj = new ConcreteRepository(myEntity, myCollectionName);
创建新实例时,typescript将确定myObj
的类型为ConcreteRepository<typeof myEntity>
。(我使用名称ConcreteRepository
来描述一个扩展AbstractRepository
的类,因为抽象类无法实例化(。
同时,static
属性应用于类本身,因此应用于每个实例。
您可以有许多AbstractRepository
实例,它们可以具有许多不同的T
值,但它们都共享相同的private static conn
值。该变量的类型为T
(因为它只设置了一次(,而不是当前实例的类型T
。
有一个依赖于泛型T
的静态变量是没有意义的
解决方案1
为了确保每个实例都有一个与其实体类型对应的SessionDb
,我们将conn
设置为实例变量,而不是静态变量。每个实例都在构造函数中设置其onthis.conn
。
export abstract class AbstractRepository<T extends Typegoose> {
protected conn: SessionDb<T>;
protected model: Model<InstanceType<T>, {}>;
constructor(entity: T, collectionName: string){
this.conn = SessionDb.connect(entity);
this.model = this.conn.getModel(collectionName);
}
}
有了这个设置,基类可以通过类来实现,这些类本身就是通用的:
export class ConcreteRepository<T extends Typegoose> extends AbstractRepository<T> {
}
或者通过与T
:的特定值绑定的类
export class SpecificRepository extends AbstractRepository<SpecificType> {
}
解决方案2
AbstractRepository
是一个abstract
类,这意味着它不能直接实例化,只能通过扩展它的类实例化来创建。如果这些扩展类都只适用于特定类型的实体,就像上面的SpecificRepository
示例一样,那么每个特定的扩展类都可以有一个单独的static conn
变量。
它看起来大概是这样的(我不知道其中一些类型的细节(:
export abstract class AbstractRepository<T extends Typegoose> {
protected model: Model<InstanceType<T>, {}>;
constructor(entity: T, collectionName: string){
this.model = this.getConnection().getModel(collectionName);
}
abstract getConnection(): SessionDb<T>;
}
export class SpecificRepository extends AbstractRepository<SpecificType> {
private static conn: SessionDb<SpecificType>;
getConnection(): SessionDb<SpecificType> {
if( SpecificRepository.conn === undefined) {
// would need to know about enity somehow, either by storing this.entity
// or by having a static entity property on the class
SpecificRepository.conn = SessionDb.connect(entity);
}
return SpecificRepository.conn;
}
}
这里,基类声明每个具体化都必须有一个方法getConnection
,该方法返回正确类型T
的SessionDb
。我们已经把这个实现留给了孩子们来解决。但是由于我们知道这个方法必须存在,所以基类在执行this.model = this.getConnection().getModel(collectionName);
时调用它是安全的