I'm using a design pattern that uses the return statement to expose public class methods.
Problem is: I'm getting a lot of JSC_INEXISTENT_PROPERTY
warnings in Closure Compiler's Advanced mode, which makes it difficult to check the warnings that actually matter.
Example of the pattern I use:
// ==ClosureCompiler==
// @pilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==
/**
* @constructor
*/
var MyClass = function() {
var someFunc = function(myString) {
console.log(myString);
}
return {
myPublicFunc: someFunc
};
}
var myClassInstance = new MyClass();
myClassInstance.myPublicFunc('Hello World');
Warnings:
JSC_INEXISTENT_PROPERTY: Property myPublicFunc never defined on MyClass \
at line 16 character 0
myClassInstance.myPublicFunc('Hello World');
Output (formatted):
(new function() {
return {
a: function(a) {
console.log(a)
}
}
}).a("Hello World");
Which is weird, because Closure understood what the code was doing and piled the code correctly, renaming myPublicFunc
consistently to a
. So why did I get this warning? Am I doing something wrong?
Note: I do not want to turn off these warnings because it would also hide warnings I actually care about. I also do not want to use quoted strings or exports because I do want Closure to press these.
I'm using a design pattern that uses the return statement to expose public class methods.
Problem is: I'm getting a lot of JSC_INEXISTENT_PROPERTY
warnings in Closure Compiler's Advanced mode, which makes it difficult to check the warnings that actually matter.
Example of the pattern I use:
// ==ClosureCompiler==
// @pilation_level ADVANCED_OPTIMIZATIONS
// ==/ClosureCompiler==
/**
* @constructor
*/
var MyClass = function() {
var someFunc = function(myString) {
console.log(myString);
}
return {
myPublicFunc: someFunc
};
}
var myClassInstance = new MyClass();
myClassInstance.myPublicFunc('Hello World');
Warnings:
JSC_INEXISTENT_PROPERTY: Property myPublicFunc never defined on MyClass \
at line 16 character 0
myClassInstance.myPublicFunc('Hello World');
Output (formatted):
(new function() {
return {
a: function(a) {
console.log(a)
}
}
}).a("Hello World");
Which is weird, because Closure understood what the code was doing and piled the code correctly, renaming myPublicFunc
consistently to a
. So why did I get this warning? Am I doing something wrong?
Note: I do not want to turn off these warnings because it would also hide warnings I actually care about. I also do not want to use quoted strings or exports because I do want Closure to press these.
Share Improve this question asked Jun 24, 2012 at 15:15 BlaiseBlaise 13.5k9 gold badges78 silver badges102 bronze badges3 Answers
Reset to default 4Your function is annotated incorrectly. It's actually not a constructor and in this case the new
keyword is unnecessary. Your function simply returns an anonymous type with a myPublicFunc
property.
To annotate such a pattern, you would use the record type:
/** @return {{myPublicFunc: function(string) }} */
var MyClass = function() {
var someFunc = function(myString) {
console.log(myString);
}
return {
myPublicFunc: someFunc
};
};
var myClassInstance = MyClass(); // new keyword not needed
myClassInstance.myPublicFunc('Hello World');
Another annotation option is to create an interface and type-cast the returned object to be that interface. This option would be useful when multiple functions return an object that conforms to the same interface.
You can also use:
/** @type {function(new:{myPublicFunc: function(string)} )} */
var MyClass = function() {...
The function can be called with "new" but doesn't return an instance of "MyClass".
Adding
MyClass.prototype.myPublicFunc = null;
would solve the problem though I don't know whether this is the best solution.
I don't really know how the piler works, but I could imagine that if you have a constructor function, it expects instance properties to be assigned to this
inside the constructor or to MyClass.prototype
.
If you remove the @constructor
annotation and omit new
, then there is not warning (but the piled code is only console.log("Hello World");
.