如何解决Typescript Generic Repository - 实例化泛型类型
我正在尝试在 Typescript 中构建一个通用存储库(使用 DynamoDB,但这无关紧要)。
我有一个接收泛型类型的基本存储库类。在这个类上,我有一个 getById
方法,它应该将实体对象作为泛型类的实例返回:
export abstract class BaseRepository<T> implements WriteInterface<T>,ReadInterface<T> {
getById(id: string): Promise<T> {
const findParams = {
TableName: this.tableName,Key: { id }
}
return this.documentClient.get(findParams).promise().then((data) => {
// this next line is my problem
// Ideally,I would just instantiate with the new() keyword.
let inst: T = new T(data.Item);
return inst;
});
}
}
我得到的上述错误是
error TS2693: 'T' only refers to a type,but is being used as a value here.
96 let inst: T = new T(data.Item);
有一些类似的问题,找到最多的答案是使用工厂函数。这种方法的问题是您仍然需要一个具体的类型来传递给工厂,但我正在尝试将工厂与泛型类型一起使用。
例如,从here我尝试过
create<T>(type: {new(): T}): T {
let newEntity: T = new type();
return newEntity;
}
getById(id: string): Promise<T> {
const findParams = {
TableName: this.tableName,Key: { id }
}
return this.documentClient.get(findParams).promise().then((data) => {
let inst: T = this.create(T);
return inst;
});
}
以上呈现与之前完全相同的错误。
我很确定有可能实现我正在尝试的目标,因为我认为 TypeORM 做了一些非常相似的事情,但我无法找到/理解它在那里是如何工作的。
后期编辑
所以,感谢 Nadia 的回答,解决方案似乎仍然是一个工厂函数,但我缺少的是通过构造函数传递类型。所以正确的实现应该是:
export abstract class BaseRepository<T> implements WriteInterface<T>,ReadInterface<T> {
protected tableName: string;
protected documentClient: AWS.DynamoDB.DocumentClient;
private create: {new (): T;};
constructor(tableName: string,create: { new (): T; }) {
this.create = create;
this.tableName = tableName;
this.documentClient = new AWS.DynamoDB.DocumentClient();
}
getById(id: string): Promise<T> {
const findParams = {
TableName: this.tableName,Key: { id }
}
return this.documentClient.get(findParams).promise().then((data) => {
let inst: T = new this.create();
return inst;
});
}
}
然后,当我想扩展这个基础存储库时,这样做的方法是:
import { BaseRepository } from './base.repository';
const tableName = process.env.DDB_TOKENS_TABLE;
export class TokenRepository extends BaseRepository<TokenEntity> {
constructor() {
super(tableName,TokenEntity);
}
}
不确定是否存在不创建特定构造函数的情况,您只需将实体传递给 super()
。
解决方法
TS 确实需要一个具体的类型,因此它知道要调用哪个构造函数。幸运的是,有一种方法可以提供 - 通过泛型类的构造函数。它看起来像这样:
class BaseRepository<T> {
private create: { new (): T; };
constructor(create: { new (): T; }) {
this.create = create;
}
getById(id: string): T {
...
let inst: T = new this.create();
...
};
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。