Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type Checking Array Contents with Closure-Compiler

In Google Closure, if an Array of a specific @type {Array.<type>} is initialized, can I be sure that Google Closure will confirm the Array contents?

Here is a small test case. It appears to me that an {Array.<string>} is sneaking past an {Array.<number>} check, although a {string} is correctly blocked by the same check. I am a little new to GC, is this an error on my part?

I've pasted this to the Google Closure Service, and I'm showing only one of two expected errors (Sept 12 2013). I've double-tested this on my local jar file (newest, v20130823) with ADVANCED_OPTIMIZATIONS and warning_level VERBOSE. It still looks like the {Array.<string>} sneaks by.

Docs: Annotating for Google Closure

Thanks in advance for your input.

// ==ClosureCompiler==
// @output_file_name default.js
// @compilation_level ADVANCED_OPTIMIZATIONS
// @warning_level VERBOSE
// @language ECMASCRIPT5
// ==/ClosureCompiler==

/**
    no warning, as expected:
    @type {Array.<number>}
*/
var a = [1,2,3,4];

/**
    warning! Type mismatch as expected:
    @type {Array.<number>}
*/
var b = 'mismatch';    // {string} does not match {Array.<number>}

/**
    no warning, but Type mismatch was expected:
    @type {Array.<number>}
*/
var c = ['foo','bar']; // {Array.<string>} should not match {Array.<number>}


// prevent compile-to-zero
alert(a);
alert(b);
alert(c);

note: I've taken a close look at this related question, where the type of Array.push() was manually filled in. This question concerns initialization, though. If I take his corrected code and init all of his arrays with garbage data, as above, GC fails to catch the garbage in his case as well.

Edited: added warning_level VERBOSE and language ECMASCRIPT5 to the header on the test case, just to be sure. {Array.<string>} still not detected.

like image 239
Z.W. Avatar asked Sep 12 '13 11:09

Z.W.


1 Answers

This is a limitation of the current type checker. The right had side is typed as "Array" (aka Array<?>) not "Array<number>" or "Array<string>" respectively, which is allowed to be assigned to any type.

It is possible to enhance to type type checker for this specific case, but it quickly breaks down in more complex cases due to the fact arrays are mutable in JavaScript. That is if "[11]" were typed to Array<number> then adding any other type would be illegal but arrays are generally not homogeneous consider:

var args = [];
args[0] = 1;
args[1] = 'foo';

So the type of Array must not be limited to initial type by default.

like image 184
John Avatar answered Nov 04 '22 13:11

John