我正在为SortedMap<string, T>
类型的对象编写一个序列化程序,并且我在序列化一个实例时使用T的实际名称填充该对象(以简化反序列化逻辑);
我想以某种方式在构造函数中执行此操作,但是我看不到可以在构造函数中调用“ T”的方法。像这样吗?
class Foo {
...
}
class SortedMap<T> {
memberTypeName : string;
constructor() {
this.memberTypeName = [some "type of T" function from which I can get the name?]
}
get(key: string) : T { ... }
add(key: string, item: T) {...}
}
let foos = new SortedMap<Foo>();
console.log(`This map contains ${foos.memberTypeName}s`);
>This map contains Foos
我以为T可能有一些方法可以让我对它表示的Type进行某种类型的反射,或者实例化T并从实例中获取其类型,但是VS Code中的intellisense没有任何意义根本没有建议,let foo = new T();
也不起作用(而且我猜想T需要具有无参数的构造函数)
我考虑过使用一个接口,该接口要求T实现knowsItsOwnName
类的属性,但是这意味着我将无法在我自己没有编写的类上使用它。另一个想法是,也许我可以在调用get时在某种代理中询问T类型,但这似乎还有很长一段路要走。
答案 0 :(得分:2)
由于将代码编译为JavaScript时类型系统为erased,因此在运行时没有<form>
。如果要使用表示T
类型名称的字符串初始化SortedMap<T>
的实例,则必须将该字符串(或可以产生该字符串的东西)传递给其构造函数。例如,假设您的目标JavaScript运行时与ES2015或更高版本兼容,则可以将T
的构造函数传递到T
的构造函数中,并利用类构造函数和函数具有{ {3}},就像这样:
SortedMap<T>
这几乎可以为您提供所需的行为:
class SortedMap<T> {
memberTypeName: string;
constructor(ctor: (new (...args: any) => T)) {
this.memberTypeName = ctor.name;
}
get(key: string): T { /* impl */ return null! }
add(key: string, item: T) { /* impl */ }
}
请注意,您不需要在let foos = new SortedMap(Foo);
foos.add("blorp", new Foo());
console.log(`This map contains ${foos.memberTypeName}s`);
// This map contains Foos
let dates = new SortedMap(Date);
dates.add("today", new Date());
console.log(`This map contains ${dates.memberTypeName}s`);
// This map contains Dates
或T
中手动指定new SortedMap(Foo)
参数,因为编译器可以从new SortedMap(Date)
的实例类型中推断出该参数。和Foo
构造函数。
无论如何,希望能有所帮助;祝你好运!
答案 1 :(得分:0)
没有简单的方法可以用语法实现所需的功能。 Since interface information is not available in runtime.
但是最实用的方法是做以下两件事之一:
1。您可以创建第一个参数为通用类型的地图:
let foos = new SortedMap(Foo);
然后在您的构造函数中,您可以访问
Foo.name
但是如果您使用类而不是接口,那将起作用。将字符串传递给构造函数将执行类似的工作,但是将使其重构,尽管它可以与任何接口和类一起使用。
2。当您的地图中至少有一个对象时。您也可以尝试获得所需的东西
firstFooObjectInMap.constructor.name
但是如果您只有对象文字而没有构造函数属性,那可能就不那么安全了。
然后,您可以编写自己的创意反射功能,该功能将打印带有控制台键的对象结构。如果您使用对象文字和接口,并且不想向构造函数添加额外的参数,则可以选择这种方法