[英]Generic Type Inference with Class Argument
我遇到一個問題,該問題是基於傳入的類型定義泛型。
我有一段代碼“激活”一個類,我無法從類型參數中獲取類型信息,因此我傳入了類對象(而不是實例)。 但是,這打破了類型推斷。
這是我要執行的操作的簡化示例:
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
參數的type
更改為any
並手動設置通用類型(如下所示)。 但是,這似乎long之以鼻,還有另一種方法可以實現這一目標。
function activator<T extends IActivatable>(type:any): T {
// do stuff to return new instance of T.
}
var classA:ClassA = activator<ClassA>(ClassA);
謝謝你提供的所有幫助。
根據語言規范,您需要通過其構造函數來引用類類型。 因此,不要使用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);
Typescript團隊建議這樣做:
基本上與blorkfish的答案相同,但提取到界面。
interface IConstructor<T> {
new (...args: any[]): T;
// Or enforce default constructor
// new (): T;
}
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: IConstructor<T>): T {
return new type();
}
const classA = activator(ClassA);
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');
您還可以在運行時從實例中獲取類型名稱,我以下面的示例格式顯示了該格式,該格式取自在運行時獲取TypeScript類名稱 :
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
僅當您要生成“相同類型的另一個”(可以獲取類型名稱,然后使用對象創建的東西來獲取另一個)時,這才有意義。
您的問題是ClassA實際上不是T類型擴展的IActivatable。 實際上,已編譯javascript中的ClassA實際上是一個返回構造函數的函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.