I compile my source with closure compiler and when i call a function that got an event object from network the application throws an error in console.
The function called is:
/**
* @param {goog.events.Event} event Socket.io-Wrapper Event.
*/
de.my.app.admin.prototype.onSaved = function(event){
var category = event.data[0].category; //<-- here it throws the error because category get compiled.
var id = event.data[0].id;
var oldid = event.data[0].oldid;
[...]
}
the event object looks like this
{ data:{
0: {
category: 'someString',
id: 5,
oldid: -5
} }
[...someMoreValuesAddedBySocketIO...]
}
that is the behavior i expected.
now i add an externs declaration like this to my externs file but i didn't alter the type declaration of the @param
at the function and the error disappears:
var xterns;
/**
* @typedef {{
* category : string,
* oldid : number,
* id : number
* }}
*/
xterns.NOTUSEDNAME;
/**
* @type {string}
*/
xterns.NOTUSEDNAME.prototype.category;
/**
* @type {number}
*/
xterns.NOTUSEDNAME.prototype.oldid;
/**
* @type {number}
*/
xterns.NOTUSEDNAME.prototype.id;
In short: I have a @param {goog.events.Event} event
declaration and an extern for xterns.NOTUSEDNAME
solves the compiler problems...
Can anyone explain why this happens?
This is a common misconception. Closure-compiler will not rename a property if any extern object contains a property of the same name. See the FAQ. If the type based optimizations are enabled, then this is no longer true and I would expect your code to break again.
To make this code type safe and compile without warnings, you would need to either:
Reference the data properties using quoted syntax event.data[0]['category']
. Your properties will never be renamed by the compiler using this method (which is often used by JSON Data).
Extend the goog.events.Event
type with a custom object that defines the data object as a strongly typed array.
Example:
/**
* @constructor
* @extends {goog.events.Event}
*/
de.my.app.AdminEvent = function() {};
goog.inherits(de.my.app.AdminEvent, goog.events.Event);
/** @type {Array.<{category:string, id:number, oldid:number}>} */
de.my.app.AdminEvent.prototype.data = [];
Depending on your exact situation, an interface might be a better option.