我正在搞乱谷歌闭包编译器中的类型检查。类型系统似乎很有用,即使不是最复杂的。我对大多数限制感到满意,但这似乎有点奇怪。
我看到为作为参数传递的函数提供类型注释的问题。特别是,如果传递函数的类型本身不固定。因此,例如,我想编写类似这样的代码:
/**
* @param {Array} xs
* @param {function(*) : boolean} f
* @return {Array}
*/
var filter = function (xs, f) {
var i, result = [];
for (i = 0; i < xs.length; i += 1) {
if (f(xs[i])) {
result.push(v);
}
}
return result;
};
filter([1,2,3], function (x) { return x > 1; });
将“--js_error checkTypes”传递给编译器,我得到这个:
test.js:17: ERROR - left side of numeric comparison
found : *
required: number
filter([1,2,3], function (x) { return x > 1; });
^
那么,怎么了?我可以指定一个参数应该是一个带有一个参数的函数,而不指定该参数的类型吗?我做错了什么,还是这只是类型检查器的限制?
Chad 建议对传递给 filter 的匿名函数进行注释,以帮助进行类型推断:
filter([1,2,3], function (x) { return /** @type {number} */ (x) > 1; });
这适用于 filter(),但似乎有点不满意(为什么编译器需要那个注解?),并且不适用于更复杂的情况。例如:
/**
* @param {Array|string} as
* @param {Array|string} bs
* @param {function(*, *): *} f
* @return {Array}
*/
var crossF = function (as, bs, f) {};
/**
* @param {Array|string} as
* @param {Array|string} bs
* @return {Array}
*/
var cross = function (as, bs) {};
var unitlist = crossF(['AB', 'CD'], ['12', '34'], cross);
似乎这里所有内容的类型对编译器来说应该是显而易见的。事实上它直接抱怨匹配函数参数的类型:
test.js:52: ERROR - actual parameter 3 of crossF does not match formal parameter
found : function ((Array|null|string), (Array|null|string)): (Array|null)
required: function (*, *): *
var unitlist = crossF(['ABC', 'DEF', 'GHI'], ['123', '456', '789'], cross);
下面接受的答案解决了这种情况。