Closure Compiler 坚持认为一个值可以为空

Closure Compiler insists a value can be null when it cannot be

我有一个类型如下的结构:

 /** @type {!Array<{
   *  cmd: string,
   *  params: !Array<{name: string}>,
   *  do: function(!Object, !Array<!Roll20Object>, !Array<string>, boolean):string
   * }>} */

加载到结构中的值之一包括以下字段:

   do: ((p,t,r,a) => {
      /** @type {!Array<string|number|boolean>} */
      let results = _.map(t, x => getTokenAttr(x,p.property));

GetTokenAttr 的 return 类型是 {null|string|number}_.map 在 underscore.js 的外部输入如下:

/**
 * Object-style annotation
 * @param {Object|Array} obj
 * @param {Function} iterator
 * @param {Object=} opt_context
 * @return {!Array|_}
 */

Closure 在编译结构时出现以下错误:

pf2utils.js:1029: WARNING - [JSC_TYPE_MISMATCH] initializing variable
found   : (Array|_|null)
required: Array<(boolean|number|string)>
                let results = _.map(t, x => getTokenAttr(x,p.property));

好像是在说results有可能是null,但不清楚这是从哪里来的。 do 声明承诺 t 参数不为空(因为它是 !Array<..>_.map 的外部承诺它不会 return 为空(因为 @return {!Array|_})。但 Closure 将 _.maps return 视为 (Array|_|null},而不是自发的。

我如何告诉 Closure 这是一个有效的赋值并且应该没有空值?

由于_被声明为class(使用@constructor),默认情况下它可以为空,类型_等同于!_|null。地图的 return 类型应该是,如果它不能 return null,则应该是 !Array|!_ 而不是 !Array|_.

您可以使用此 snippet 在 Closure 编译器 "debugger" 游乐场中验证差异,其中允许分配给 x 但拒绝分配给 y :

/** @constructor */
function _() {}

/** @type {!Array|_} */
let x = null;  // valid

/** @type {!Array|!_} */
let y = null;  // type error