removeChild 出现意外 JSC_TYPE_MISMATCH 错误

Unexpected JSC_TYPE_MISMATCH error with removeChild

当我编译以下代码时

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

// ADD YOUR CODE HERE
let source;
function v() {
  const me = document.createElement('div');

  function setSource() {
    if (source) {
      me.removeChild(source); // line 8
      source = undefined;
    }
    source = document.createElement('div');
  }
}

在在线闭包编译器中,https://closure-compiler.appspot.com我得到以下错误:

JSC_TYPE_MISMATCH: actual parameter 1 of Node.prototype.removeChild does not match formal parameter
found   : (Element|undefined)
required: (Node|null) at line 8 character 23
        me.removeChild(source);

我期望发生的是它会推断出 source 不能在第 8 行未定义,因此不会抱怨对 removeChild() 的调用。实际上,在一些更简单的例子中,它似乎就是这样做的。

source 的类型肯定是 (Element|undefined) 在条件之外,所以它可能只是不打算工作?

我想知道是否应该提交错误报告。

在线编译器说此代码无法编译,但也许它将零输出和非零警告一起解释为错误?这个例子是从一些有实际副作用并且编译成功的代码中提炼出来的。

更新:这是按预期工作的:https://github.com/google/closure-compiler/issues/2382

指定 source 的类型,它起作用了。这个compiles with the online compiler.

/** @type {Element|undefined} */
let source;
function v() {
  const me = document.createElement('div');

  function setSource() {
    if (source) {
      me.removeChild(source); // line 8
      source = undefined;
    }
    source = document.createElement('div');
  }
}

但您可能是正确的,这是一个编译器错误。如果编译器猜测 source 的类型为 {Element|undefined},那么它应该在第 8 行推断出 source 的类型为 {Element}

然而,当您知道它们的类型时,通常最好告诉编译器它们是什么类型。否则编译器必须猜测,并且可能在编译过程中没有足够早地猜测类型,因此你会得到这种 "bug".

推测:如果没有类型注释,编译器会通过查看分配给 source 的其他代码来猜测 source 的类型。由于 document.createElement returns Element 和另一行代码分配 source = undefined 猜测来源类型是 {Element|undefined} 是合理的。