我遇到了一个问题,即根据我传入的类型来定义一般类型。
我有一段代码巫婆“激活”一个类,我无法从类型参数中获取类型信息,所以我在类对象(不是实例)中传递。然而,这打破了类型推断。
以下是我尝试做的简化示例:
interface IActivatable {
id: number;
name:string;
}
class ClassA implements IActivatable {
public id: number;
public name: string;
public address:string;
}
class ClassB implements IActivatable {
public id: number;
public name: string;
public age: number;
}
function activator<T extends IActivatable>(type:T): T {
// do stuff to return new instance of T.
}
var classA:ClassA = activator(ClassA);
到目前为止,我能够提出的唯一解决方案是将type
参数的类型更改为any
并手动设置泛型类型(如下所示)。然而,这似乎很长,有另一种方法来实现这一目标。
function activator<T extends IActivatable>(type:any): T {
// do stuff to return new instance of T.
}
var classA:ClassA = activator<ClassA>(ClassA);
感谢您提供任何帮助。
答案 0 :(得分:37)
根据语言规范,您需要通过它的构造函数来引用类类型。因此,不要使用type:T
,而是使用type: { new(): T;}
,如下所示:
function activator<T extends IActivatable>(type: { new(): T ;} ): T {
// do stuff to return new instance of T.
return new type();
}
var classA: ClassA = activator(ClassA);
答案 1 :(得分:6)
这就是Typescript团队推荐的方式:
基本上与blorkfish的答案相同,但提取到界面。
func IsMatchingRegex(s string, regex string) bool {
return regexp.MustCompile(regex).MatchString(s)
}
答案 2 :(得分:5)
TypeScript中的类型信息在编译期间都被擦除,因此您不能直接使用任何泛型类型,例如,在运行时。
所以这就是你能做的......
您可以通过将名称作为字符串传递来按名称创建类。是;这涉及挥动你的魔法棒。您还需要了解工具链中可能影响名称的任何内容,例如任何会破坏名称的缩小器(导致您的魔术字符串不同步):
class InstanceLoader<T> {
constructor(private context: Object) {
}
getInstance(name: string, ...args: any[]) : T {
var instance = Object.create(this.context[name].prototype);
instance.constructor.apply(instance, args);
return <T> instance;
}
}
var loader = new InstanceLoader<IActivatable>(window);
var example = loader.getInstance('ClassA');
您还可以在运行时从实例中获取类型名称,我在下面的示例格式中显示了Obtaining TypeScript Class Names at Runtime:
class Describer {
static getName(inputClass) {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((<any> inputClass).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
}
}
class Example {
}
class AnotherClass extends Example {
}
var x = new Example();
var y = new AnotherClass();
alert(Describer.getName(x)); // Example
alert(Describer.getName(y)); // AnotherClass
只有当你想要生成“另一种相同类型”时,这才有意义,因为你可以获取类型名称,然后使用对象创建东西来获得另一种。
答案 3 :(得分:0)
你的问题是ClassA实际上并不是T类型的扩展IActivatable。实际上,编译的javascript中的ClassA实际上是一个返回构造函数的函数。