Reputation: 773
I can't figure out how to send class references as function arguments, so that Google Closure compiler will compile it right in advanced mode. In the below example I send a class reference to the Test1.doSomething function, which invokes a static function on the class. I've set the @param to Function, because I guess it still is a function, although I use ES6 style classes. Is there some other keyword I should use?
The below code works fine uncompiled, and also works fine if I go old school and change "class Test2" into "function Test2()". I've also tried to change the @param into function(), function(new:Test2), function(this:Test2), typeof Test2, etc, with no success.
class Test1
{
/**
* @param {!Function} typeRef
*/
doSomething(typeRef)
{
typeRef.doSomething();
}
}
class Test2
{
}
Test2.doSomething = function()
{
alert(1);
}
var t1 = new Test1();
window["t1"] = t1;
t1.doSomething(Test2);
I compile as follows:
--debug --formatting=PRETTY_PRINT --language_in ECMASCRIPT6_STRICT --language_out ECMASCRIPT6_STRICT --compilation_level ADVANCED_OPTIMIZATIONS --js Test.js --js_output_file Script.js
The result with "class Test2"
'use strict';
class $Test1$$ {
}
window.t1 = new $Test1$$;
The result with "function Test2()"
'use strict';
class $Test1$$ {
$doSomething$($typeRef$$) {
$typeRef$$.$doSomething$();
}
}
function $Test2$$() {
}
$Test2$$.$doSomething$ = function $$Test2$$$$doSomething$$() {
alert(1);
};
var $t1$$ = new $Test1$$;
window.t1 = $t1$$;
$t1$$.$doSomething$($Test2$$);
EDIT ON 29 JAN: Added a more complete example of what I'm trying to do:
class Car
{
constructor()
{
this.make = "Ford";
console.log("Car created.");
}
}
Car.create = function(registry)
{
let obj = new Car();
registry.add(obj);
return obj;
}
class Motorcycle
{
constructor()
{
this.make = "BMW";
console.log("Motorcycle created.");
}
}
Motorcycle.create = function(registry)
{
let obj = new Motorcycle();
registry.add(obj);
return obj;
}
class Registry
{
constructor()
{
this.vehicles = [];
}
add(vehicle)
{
this.vehicles.push(vehicle);
}
makeVehicle(typeRef)
{
typeRef.create(this);
}
}
function init()
{
var registry = new Registry();
registry.makeVehicle(Car);
registry.makeVehicle(Motorcycle);
registry.makeVehicle(Motorcycle);
registry.makeVehicle(Car);
registry.makeVehicle(Car);
}
Upvotes: 1
Views: 472
Reputation: 7389
To pass in a class, you can use the {typeof namespace}
type:
@param {typeof Test2} TypeRef
As in your code:
class Test1
{
/**
* @param {typeof Test2} TypeRef
*/
doSomething(TypeRef)
{
(new TypeRef()).doSomething();
}
}
class Test2
{
doSomething ()
{
alert(1);
}
}
var t1 = new Test1();
window["t1"] = t1;
t1.doSomething(Test2);
Demo (don't forget to hit Compile)
When using @param
(without typeof
) you would pass an instance of that type*. This is far more common than passing a class itself
*: Sorry if this is not relevant but I noticed a couple of issues in the original code and wanted to show you how to fix them, even if not relevant;
To produce an instance-typed version, I had to change 3 things;
1) The Test2.doSomething
assignment should be assigning to Test2.prototype
;
Test2.prototype.doSomething = function()
{
alert(1);
}
Or using the ES6 Class format:
Test2
{
doSomething()
{
alert(1);
}
}
2) And to resolve a warning Test1.doSomething
's @param
annotation had to become Type2
, as Function does not declare a Function.doSomething
method.
/**
* @param {!Type2} typeRef
*/
3) The final line passes the class itself, not an instance of the class, so you should use the new
operator to send in an instance of that class.
t1.doSomething(new Test2());
Cheers.
Upvotes: 1