我正在使用反射元数据库和Typescript装饰器。
例如,我有一个此类(实际的类别会有更多的字段):
class Message {
@FieldTyping
text: string;
@FieldTyping
code: number;
constructor(text: string,code: number) {
this.text = text;
this.code = code;
}
}
Decorator也很综合,但是在实际代码中,它最终做到了:
function FieldTyping(target: Object,key: string) {
Reflect.getMetadata('design:type',target,key)
// "String" output in console for "text" key
}
现在它可以正常工作,但是我想减少样板。所以我想使用一个装饰器并在构造器中声明所有字段,例如:
@ClassTyping
class Message {
constructor(public text: string,public code: number) { }
}
装饰器应遍历所有公共字段,并与FieldTyping
做相同的工作-从反射中获取实际的类型。所以我想要两件事:
- 从课程中获取所有键。 (因为我只需要
string
个名字) - 以
target
的身分Reflect.getMetadata
。
但是类装饰器中的target
是构造函数,而不是Object
。我可以通过一些“ hack”访问类密钥:
type ConstructorType<T> = {
new (...args: any[]): T
}
function ClassTyping<T>(target: ConstructorType<T>) {
const obj = new target()
const fields = Object.keys(obj)
fields.map(prop => Reflect.getMetadata('design:type',field))
// "undefined" output for all fields
}
因此,我使用undefined
值创建类实例,并在不知道其实际类型的情况下获取其键(公共字段)。但是我对target
有疑问。我尝试在此上下文中使用任何变体,而不是实际的target
参数:
-
target.prototype
,以便从其构造函数中获取Object
; -
obj
作为此Object
的新实例; - 只是
Message
作为类型
但是它们都不起作用,在所有情况下我都得到“未定义”类型。根据我的实验,即使没有装饰器和简单的参数,Reflect.getMetadata
在其他任何地方似乎也无法正常工作
Reflect.getMetadata('design:type',Message,"text")
显然,它与字段装饰器中的target
仅 兼容,至少对我而言。在这个主题下,我被整个SO所困扰,找不到适合我特定目的的合适解决方案。
所以请告诉我这是否可能或我想念的是什么。
请注意:
- 我知道使用regex绝对可以,但是我不想要这种难看的解决方案。
- 这是客户端代码,因此,例如,我无法访问文件系统并解析源以获取ts-morph的类型(或者再次缺少内容)
- 我确实在我的
"emitDecoratorMetadata": true
中有tsconfig.json
- 我的堆栈只是NPM和作为捆绑器的包裹。在本地环境中与Parcel dev服务器一起使用,在“生产”中(在Heroku上)与Harp一起使用。