I can’t understand how to get the google closure compiler for javascript to properly recognize properties of a constructor. For example, in the code below, I don’t know what type to give ‘cls’ in line 27 so that the compiler does NOT produce the following (erroneous in my opinion) error:
foo.js:29: WARNING – Property say never defined on cls
cls.say();
^
From reading the documentation it seems that I should be doing it as I do in 25. Can someone help please? Thanks,
1 /**
2 * @interface
3 **/
4 function Sayer() {}
5 Sayer.prototype.say = function() {};
6 Sayer.say = function() {};
7
8 /**
9 * @constructor
10 * @implements {Sayer}
11 **/
12 function A() {}
13 A.say = function() { console.log('A factory'); };
14 A.prototype.say = function() { console.log('Am an A'); }
15
16 /**
17 * @constructor
18 * @implements {Sayer}
19 **/
20 function B() {}
21 B.say = function() { console.log('B factory'); };
22 B.prototype.say = function() { console.log('Am an B'); };
23
24 /**
25 * @param {function(new:Sayer)} cls
26 **/
27 function makeSayer(cls) {
28 var obj = new cls();
29 cls.say();
30 obj.say();
31 }
32
33 makeSayer(A);
34 makeSayer(B);
“Sayer.say” on the interfaces is ignored.
Are you trying to prepare this for Closure’s advanced mode? In advanced mode “A.say” and “B.say” are renamed to “A$say” and “B$say”, the type check expects this and complains about it appropriately (there won’t be a method A.say).
You can avoid collapsing by have it added by it indirectly:
I suppose you could avoid the type warning by adding a line like:
But I’m not sure you this is what you want.
You can avoid the hassle and add it to the prototype and call that instead: