【问题标题】:How to annotate in javascript a class that extends a generic type, using closure compiler如何使用闭包编译器在javascript中注释扩展泛型类型的类
【发布时间】:2015-03-15 10:29:16
【问题描述】:

我在 javascript 中创建了一个类工厂,它采用 T 类型并生成一个 T 类型的新增强类,很简单。

我正在使用google的闭包编译器来编译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);

当我用闭包编译器编译这段代码时,我得到一个编译器警告:

'无法解析增强的@extends 标记中的类型'。

所以,很明显编译器不知道在编译这个类时从哪里推断出 T。

有人可以指出为什么编译器在创建类时无法推断类型,或者是否有办法将生成的类注释为扩展类型 T。

【问题讨论】:

  • 我认为我们不支持这样的案例。我们希望在编译时知道继承层次结构:也就是说,可以扩展 Foo 或扩展 Bar,但不要说“我正在扩展 Foo 或 Bar,不确定哪个”。你能描述一下你为什么想做这样的事情吗?也许还有另一种方式,比如让 Foo 和 Bar 实现相同的接口。
  • MatrixFrog,我的用例是类工厂,其中类不能被注释,因为它们是在运行时创建的。唯一的方法是创建一个扩展 的虚拟类(接口不能扩展),其中 T 是泛型类型(模板类型),然后将工厂的返回类型注释为 {function(new:Enhanced&lt;T&gt;)} 其中 Enhanced 扩展 @ 987654325@

标签: javascript generics annotations extends google-closure-compiler


【解决方案1】:

我的用例是类工厂,因为类是在运行时创建的,所以无法对其进行注释

听起来 Closure Compiler 可能无法在这方面为您提供帮助,至少在这种特殊方法下无法提供帮助。

您希望Enhanced 成为一个接受一个类并返回一个类的函数。肯定有一些语言以这种方式对类进行操作(Python、Javascript、Ruby 等)。

但是闭包编译器需要静态类才能进行静态分析。这不一定是它必须工作的方式,但这就是它的设计工作方式。

一个粗略的经验法则是这样的:如果你能用 Java 表示类型,你就可以用闭包注解表示类型。

当然,这不是 GWT;你不是在写Java。你可以使用你的 JS-fu 来编写你想要的所有元类。但不要指望闭包编译器一定能够对它进行类型检查。


好消息是,在遵循这种静态类范式的语言背后确实有数十年的研究和最佳实践:C++、Java、C#。如果您熟悉这些,您可能会问自己“我将如何在这些语言中做到这一点?”

您的实际问题(无论是什么)可能已经通过这些 OO 语言的设计模式解决了数百或数千次,您也可以这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-07
    • 2021-05-13
    • 2019-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多