在Closure中检测接口和鸭子类型

时间:2016-03-18 18:25:28

标签: javascript google-closure-compiler google-closure

Closure库中有几个地方接口有一对addImplementation/isImplementedBy函数来对接口进行运行时类型检查(类似于this answer)。我并不完全是这个解决方案的粉丝,我有一些非常简单的东西。有没有办法在启用ADVANCED_OPTIMIZATIONS的情况下进行鸭子打字?假设我有一个界面,以及对具有该界面的儿童采取特殊操作的组件,例如:



/** @interface */
MyInterface = function() {};

MyInterface.prototype.doSomething = function() {};

/**
 * @constructor
 * @extends {goog.ui.Component}
 */
MyComponent = function() {
   ...
};

/** @inheritDoc */
MyComponent.prototype.addChild = function(child, opt_render) {
  goog.base(this, 'addChild', child, opt_render);
  if (child.doSomething) {
    child.doSomething();  
  }
};




ADVANCED_OPTIMIZATIONS会不断重命名" doSomething"属性与实现?如果没有,会添加一个类型联合确保它会吗? e.g。



/**
 * @param {goog.ui.Component|MyInterface} child
 */
MyComponent.prototype.addChild = function( child, opt_render) {
  if (child.doSomething) {
    child.doSomething();  
  }
};




2 个答案:

答案 0 :(得分:2)

这是添加@record的内容。您需要使用最新版本的编译器才能使用它(至少在2016年有所作为)。

只需将@interface替换为@record即可获得所需的行为。编译器将一致地重命名。

答案 1 :(得分:1)

我把Chad的答案作为决议留下了,但是一旦我完成编辑工作就重新审视了这个问题,并且为了后人的缘故,我发布了一个更详细的答案来解决鸭子打字的一般情况。

您可以使用ADVANCED优化执行动态向下转换,如下所示:

var maybeRecordType = /** @type {MyRecordType} */ (someObject);
if ( maybeRecordType.propertyInQuestion ) {
  maybeRecordType.propertyInQuestion();
}

如果传递的两种可能类型之间的属性名称发生冲突,那么显然会以这种方式丢失编译时检查,但这总是存在使用duck typing的风险。