【发布时间】:2019-07-23 20:39:15
【问题描述】:
我正在尝试使用 TypeScript 为 node.js 和 MongoDB 构建一个类似于“实体框架”的 ORM 库。
使用这个库,消费者将能够定义一个模型类(例如Person)来扩展Base 类,并且类装饰器将向 Person 类添加额外的数据(例如,@ 987654324@ 数组,将包含模型的所有实例,collection_name 将是模型的 MongoDB 集合名称等)。
TypeScript playground 中的代码。
所以我的第一步是创建一个Base 类:
class Base<T>
{
static collection_name: string
static instances: Base<any>[]
_id: string
}
所以用户可以像这样定义他的模型:
@decorator<Person>({collection_name: 'people'})
class Person extends Base<Person>
{
@field name
@field address
...
}
然后我创建了一个装饰器类来设置 Person 类的 collection_name 和 instances 属性:
function decorator<T>(config: { collection_name: string }) {
return function <T extends Base<T>>(Class: IClass<T>) {
Class.collection_name = config.collection_name;
Class.instances = [];
return Class
}
}
装饰器函数接收用户生成的Class,我正在尝试创建一个接口来描述此类的类型。我叫它IClass:
interface IClass<T>
{
new(): Base<T>
instances: Base<T>[];
collection_name: string
}
-
new是构造函数(返回Base实例) -
instances和collection_name是Base<T>的静态属性,在这里是非静态的(我不确定,对吗?)
但是,当尝试定义用户模型时,我收到以下错误:
@decorator<Person>({collection_name: 'people'}) // <==== ERROR HERE ===
class Person extends Base<Person>
{
}
错误:(23, 2) TS2345: 'typeof Person' 类型的参数不是 可分配给“IClass>”类型的参数。
“typeof Person”类型中缺少属性“instances”,但 类型“typeof Person”缺少类型中的以下属性 在类型“IClass>”中是必需的。
在检查typeof Person 的类型时,打字稿编译器似乎忽略了从Base 继承的静态成员。
如何定义装饰器函数的Class属性的类型?
【问题讨论】:
-
type PersonConstructor = typeof Person;然后使用@decorator<PersonConstructor> -
@PatrickRoberts 感谢您对编辑的评论。但是......不,这没有成功,仍然是同样的错误。另外,Person 类是一个用户定义的类,所以我试图让语法尽可能简单、简短和可用
-
很公平,没有尝试过,只是看起来这可能是查看您最初错误的技巧。让我看看我是否真的可以让你的例子工作,我会告诉你的。
-
您的直接问题是
decorator()返回一个函数,该函数只接受 已经 类型为IClass<T>... 但您正试图采用 任何构造函数并返回IClass<T>,对吗? -
我找到了一个可行的解决方案,jcalz 是对的。我现在正在发布答案。您需要将您的界面分成两部分才能完成这项工作。
标签: node.js typescript typescript-generics typescript-decorator typescript-class