Search code examples
javascripttypesnullminifygoogle-closure-compiler

Closure compiler thinks a parameter is mismatched due to a null condition that never happens


I am using the google closure compiler to minify my code and I recently added JSDoc annotations to allow the compiler to do type checking and better minification (in advanced mode). Unfortunately, it is displaying a warning. Is there a way I can change the code to prevent the warning without adding a closure compiler comment to suppress it?

JSC_TYPE_MISMATCH: actual parameter 1 of add does not match formal parameter
found   : (Date|null)
required: Date at line 30 character 8
    add(date, 1, "second");
        ^

Here is the JS code I am trying to minify

/**
 * @param {?Date|*} date
 * @returns {!boolean}
 * @private
 */
function isValidDateObject(date) {
    return (date instanceof Date) && !isNaN(date.getTime());
};

/**
 * @param {!Date} date
 * @param {!number} num
 * @param {!string} unit
 */
function add(date, num, unit) {
    if (unit === "second") {
        date.setSeconds(date.getSeconds() + num);
    }
}

/**
 * @param {Date} date
 * @return {Date}
 */
function addOneSecond(date) {
    if (!isValidDateObject(date)) {
        return date;
    }

    add(date, 1, "second");
    return date;
}

The date instanceof Date check should handle date being null and make the method return false and not even try to all the add function. Not sure why cc is thinking I could be passing null to the add function. In the real code, isValidDateObject is used in many places so I don't want to inline it.

You can minify my code by using the online version of the closure compiler and setting the optimization level to "Advanced".

Note: this is a simplified example to show off the error I am receiving.


Solution

  • Closure is not smart enough to determine that isValidDateObject() will check and only return if it's a valid date object, so you need to hint to closure that you are indeed passing a Date object to your function at that point:

    add(/** @type {!Date} */ (date), 1, "second");