Use interfaces instead of namespaces in externs #1223
Description
Currently, tsickle creates one namespace per file in externs, declares exported members as properties of such a namespace, and pass it around to express import * as ns
syntax. This seems to be causing closure compiler to be overly conservative on property mangling, according to google/closure-compiler#2132.
This have had positive effects, namely, it has hided many problems with generated externs -- sometimes the generated externs skips over some properties over a namespace, but apparently the above issue make closure compiler to safely back off on such non-declared properties. But now this is being worked on, IMO tsickle could switch to interface-per-file format as described in the above issue. It would have another benefit of expressing export * from '...'
syntax cleanly as multiple @extends
.
I am not sure whether the below is a good closure compiler annotation, but it seems to be compiling well.
/** @externs */
/**********************************************************************/
/** @interface */
var intf1 = function() {};
/**
* @constructor
* @struct
*/
intf1.prototype.X = function() {};
/** @type {string} */
intf1.prototype.X.prototype.foo;
/** @type{!intf1} */
var myNs1;
/**********************************************************************/
/** @interface */
var intf2 = function() {};
/**
* @record
* @struct
*/
intf2.prototype.Y = function() {};
/** @type {string} */
intf2.prototype.Y.prototype.bar;
/** @type {!intf2} */
var myNs2;
/**********************************************************************/
/**
* @interface
* @extends {intf1}
* @extends {intf2}
*/
var intf = function() {};
/** @type {!intf} */
var myNs
/**
* @fileoverview
* @suppress {uselessCode}
*/
myNs.X;
(new myNs.X()).foo;
(new myNs.X()).bar; // [JSC_INEXISTENT_PROPERTY] Property bar never defined on intf1.prototype.X
/**
* @param {intf1.prototype.X} x
* @param {intf2.prototype.Y} y
*/
function g(x, y) {
x.foo = y.bar;
x = y; // [JSC_TYPE_MISMATCH] assignment found : ... required : ...
}
myNs.Z // [JSC_INEXISTENT_PROPERTY] Property Z never defined on intf
(Moved from #1220 (comment))