我正在使用反射元数据库和 Typescript 装饰器。
例如,我有这个类(真正的会有更多的字段):
class Message {
@FieldTyping
text: string;
@FieldTyping
code: number;
constructor(text: string, code: number) {
this.text = text;
this.code = code;
}
}
装饰器也很合成,但在实际代码中它最终会这样做:
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', target, field))
// "undefined" output for all fields
}
所以我用undefined
值创建类实例并在不知道它的实际类型的情况下获取它的键(公共字段)。但我有问题target
。我试图在这种情况下使用任何变体而不是实际target
参数:
target.prototype
为了从中获取Object
构造函数;obj
作为 this 的一个新实例Object
;- 就像
Message
一种类型
但是它们都不起作用,在所有情况下我都得到了“未定义”类型。从我的实验来看,即使没有装饰器和简单的参数,似乎在任何其他地方Reflect.getMetadata
也不起作用:
Reflect.getMetadata('design:type', Message, "text")
显然它只适用于现场target
装饰器,至少对我来说。我在这个主题中挖掘了整个 SO,但没有找到任何适合我特定目的的解决方案。
所以请告诉这是否可能或我错过了什么。
注意:
- 我知道使用正则表达式绝对有可能,但我不想要这种丑陋的解决方案。
- 它是客户端代码,因此我无法访问文件系统并解析源以获取ts-morph类型,例如(或者我又错过了一些东西)
- 我确实有
"emitDecoratorMetadata": true
_tsconfig.json
- 我的堆栈只是 NPM 和 Parcel 作为捆绑器。在本地环境中与 Parcel 开发服务器一起使用,在“生产”中与 Harp 一起使用(在 Heroku 上)。