closure-compiler
closure-compiler copied to clipboard
Type Only Import Reference
A key component to avoiding circular dependencies is the option to reference a type without importing the module.
Example:
import ModelEvent from './model-event';
export default class Model extends EventTarget {
changeItem(item) {
this.item = item;
this.dispatchEvent(new ModelEvent('change:'+item.name, this, item));
}
}
import Model from './model';
export default class ModelEvent extends Event {
/**
* @param {string|!goog.events.EventId} type Event Type.
* @param {!Model} model
*/
constructor(type, model) {
}
}
We need a way (without requiring closure-library) to import or reference a type from another module.
Has there been any movement on this subject? I've been looking for a way to do exactly this, without much success.
This is possible already. See https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/runtime_tests/module_tests/module_test_resources/referenceOtherModule.js
Needs to be documented better.
@MatrixFrog It's nice that we have the runtime tests open sourced.
Yup. We don't have an easy way for non-Googlers to run them though :(
@MatrixFrog Eventually we should switch the external build system to Bazel and use https://github.com/bazelbuild/rules_closure for them.
I'm sure I'm overlooking something simple, but is there a way to do this without requiring a parameter to be passed from one function to another? For example, if I were to deliberately setup circular factories:
// Left.js
export class Left {
constructor() { console.log("You've created a left-hand node!"); }
createRight() { return new Right(); }
}
... and ...
// Right.js
export class Right {
constructor() { console.log("You've created a right-hand node!"); }
createLeft() { return new Left(); }
}
I could import Left into Right, or vice-versa, but I can't import them both into each other. If they were defined in the same file, then variable hoisting would take care of the problem; but putting them in the same file isn't always a great solution.
In some languages (e.g. C) this could be resolved by creating a header file with declarations, and then a source file with definitions. Is there a similar behavior in Closure Compiler?
To clarify, this bug covers the case when the module in question is included in the compilation unit, but we don't want to explicitly import it in our module.
There is another use case for type-only imports which we currently don't support, but we'd like to. One should be able to import some module only for types, and be sure that the code of that module won't be included in the output, even if it has side effects.
Ah, ok. Your second paragraph was what I was hoping to do. Thank you all for your time!
The test file is gone. Can anyone point to a solution?
CC @froxieye
I think the test file might be gone because we un-implemented this feature? But that is only a very vague memory, I'm not sure.
As far as syntax goes, FWIW the latest typescript added jsdoc support for this to do
@param {!Model} model
with
@param {!import('./model')} model
(since it's the default export in the given example, dot access available if not. Can also reference in a typedef if the type is needed throughout the file).
+1 for import('./module').Type
like it's 2018 that means the JS files can also be transpiled OK.
@jplaisted can you comment on the current state of this?
Looks like code like this at least used to work as a way of referring to types in other files without importing them.
/**
* @param {./exportClass.Parent} parent
*/
export default function(parent) {
return parent.constructor.staticFunction();
}
The test file we had for it was module_test_resources/referenceOtherModule.js
,
but that got deleted over a year ago.
@MatrixFrog says he thinks we unimplemented this feature.
Created Google internal issue b/119831043
@MatrixFrog is correct. It was not used, did not have robust testing, and used "." as a delimiter, so we removed it.
Using syntax based on dynamic import is a lot more idiomatic, though as I've discovered non-trivial to land due to our JSDoc parser. I still haven't had the time, and will bring this up again at future planning meanings.
@jplaisted has there been any further discussion on this with all the other ES improvements made to the compiler? Or is there another recommended approach to type-only import references? Thank you!