3

我在JavaScript中创建了一个类工厂,它采用类型T并生成一个新的类型为T的增强类,简单。如何在JavaScript中注释扩展泛型的类,使用闭包编译器

我正在使用谷歌的闭包编译器来编译javascript,以及用于注释类型的闭包注解等。挑战在于如何注释一个扩展类型T的类,其中T是泛型类型。

这里是扩展其他类型的简化类Enhanced

/** 
* @constructor 
*/ 
function Foo(){ 
    this.x = 'x'; 
}; 

/** 
* @constructor 
*/ 
function Bar(){ 
    this.y = 'y'; 
}; 

/** 
* @constructor 
* @param {function(new:T)} FooOrBar 
* @extends {T} 
* @template T 
*/ 
function Enhanced(FooOrBar){ 
    FooOrBar.call(this); 
    this.z = 'z'; 
}; 

/** @type Enhanced.<Foo> */ 
var enhancedFoo = new Enhanced(Foo); 

/** @type Enhanced.<Bar> */ 
var enhancedBar = new Enhanced(Bar); 

当我编译这个代码与封闭的编译器,我得到一个编译器警告:

“不能在解决型@扩展了Enhanced的标签。

所以,显然编译器不知道从何处推断T何时编译此类。

有人请指出为什么编译器无法推断出类型创建类的时候,或者如果有注释生成的类作为

+0

我不认为我们支持这样的情况。我们希望在编译时知道继承层次结构:也就是说,可以扩展Foo或扩展Bar,但不要说“我在扩展Foo或Bar,不知道哪个是。”你能描述一下你为什么要这样做吗?也许还有另一种方式,比如让Foo和Bar实现相同的界面。 – MatrixFrog

+0

MatrixFrog,我的用例是Class工厂,因为它们是在运行时创建的,所以类不能被注释。唯一的方法是创建一个虚拟类(接口不能扩展),它扩展了,其中T是泛型类型(模板类型),并且将工厂的返回类型标注为'{function(new:Enhanced )}'其中'Enhanced'扩展'T' –

回答

2

我的使用情况是扩展型T.方式班级无法注释的班级,因为他们是在运行时创建的

听起来像Closure编译器可能无法帮助你在这里,至少不是这种特定的方法。

你打算Enhanced是一个函数,它接受一个类并返回一个类。当然也有以这种方式对类进行操作的语言(Python,Javascript,Ruby等)。

但是Closure Compiler需要静态类才能进行静态分析。这不一定是的工作方式,但这是它设计的工作方式。

一个粗略的经验法则是:如果您可以用Java表示类型,则可以表示Closure注释中的类型。

当然,这不是GWT;你不是在写Java。你可以用你的JS-fu编写你想要的所有元类。但不要指望Closure编译器必须能够输入检查它。


好消息是,有字面上几十年的研究和遵循这种模式的静态类的语言背后的最佳实践:C++,Java和C#。如果你熟悉这些,你可能会问自己:“我怎么用这些语言来做到这一点?”

您的实际问题(不管它是什么)可能已经通过这些面向对象语言的设计模式解决了数百或数千次,您也可以这样做。