Google Closure Compiler数组的类型注释

3
在使用Google Closure Compiler进行测试时,我发现一个例子中无法强制编译器对错误变量类型进行警告。我使用了以下示例:
/** @typedef ({name: string, token: string}) */
var pendingItem;

/** @type (Array.<pendingItem>) */
var pending = [];

// NOTICE: the token is intentionally misspelled as "toke" to cause a warning
var dummyItem = {
  name: 'NameHere',
  toke: 'SomeToken' 
};

// This should cause a warning, because of the 
// type mismatch (toke instead of token)
pending.push(dummyItem);

// Do something useful so that the whole code wouldn't be optimized to 0 bytes
alert(pending.length);

而且代码编译完美,没有给出预期类型的警告。但是如果您使用:
pending[1] = {
  name: 'Second Name',
  toke: 'Second Token'
}

您会收到预期的类型不匹配警告。
我理解这可能是因为`push`没有定义类型检查,因为它是一个内置函数。预期定义`pending`作为`pendingItem`数组可以强制执行,但默认情况下并不会强制执行。
问题是是否以及如何向已定义的函数(如`push`)添加类型检查,以便在上面的示例中发出警告。我也了解到,为了实现类似的结果,一种方法是在`dummyItem`之前添加`/** @type {pendingItem} */`来强制类型,但出于教育目的,我想知道如何向像`push`这样的函数添加类型检查(或者更严格地定义`pending`本身)。
此外,有人能解释一下重命名对象属性的逻辑吗?如果编译上面的示例,它不会重命名`dummyItem`的属性`name`,但它会将`token`重命名为`a`。
1个回答

3
为了在push上强制类型检查,必须使用正确的类型重新定义它。注意,使用对象字面量符号时,你必须使用@type而不是@param来定义类型,因为我们要将函数分配给对象的参数,而不是定义一个普通函数。在这种情况下,代码应该如下所示:
/** @type {function(pendingItem)} */
pending.push = function(item) {
  Array.prototype.push.call(pending, item);
};

现在,当尝试编译以下内容时:
// Still an intentionally misspelled "toke"
var dummyItem = {
  name: 'NameHere',
  toke: 'SomeToken' 
};

// First warning
pending.push(dummyItem);

// Second warning
pending[1] = {
  name: 'Second name',
  toke: 'Second Token'
};

然后两者都会生成一个类型不匹配的警告,就像预期的那样。

想到这可能对将来的某些人有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接