Not sure this even allowed, but it seems like a reasonable request. Encountered during the transition of require to ES6 modules.
As an example:
Foo.ts
class Foo {}
export default Foo;
Bar.ts
export * from './Foo';
Foo.js
exports.default = Foo;
Bar.js
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
__export(require('./Foo'));
The re-exported object here is now named default.
I assume the following would work:
export {default as Foo} from './Foo'
Or special handling for default:
function __export(m) {
if ('default' in m) {
// What name here?
exports['notDefault'] = m['default'];
delete m['default'];
}
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
__export(require('./Foo'));
looking at the ES6 spec, it should be an error to do that (section 15.2.1.16.3):
If SameValue(exportName, "default") is true, then
a. Assert: A default export was not explicitly defined by this module.
b. Throw a SyntaxError exception.
c. NOTE A default export cannot be provided by an export *
so in this in Bar.ts export * from './Foo'; should have been flagged as an error since module Foo defines a default, and module Bar does not.
@mhegazy Hey thanks for looking at this so quickly and the ES6 section! Kind of interesting this is not applicable. Seemingly the solution is to:
export {default as Foo} from './Foo'
Since the following does not work either:
export Foo from './Foo'
Closing as invalid with ES6 spec. I'll reopen if you want to handle the assertion error.
I will keep it open for the compiler to issue a compile-time warning for this case.
k thanks!
I don't think there is a bug here, nor am I sure a warning is warranted.
In the example above, there is nothing wrong with the export * in Bar.ts and I don't think it should cause a compile-time error or warning. It is perfectly fine for a module Bar.ts to not have a default export and at the same time export * from a module Foo.ts that does have a default export. However, the default export from Foo.ts is ignored by the export * and does not become the default export of Bar.ts (i.e. Bar.ts will have no exported member named default). That is indeed what the compiler does right now, and if you try to import the default export of Bar.ts you'll get an error saying Bar.ts has no default export.
You could perhaps argue our __export helper function should check for and exclude properties named default, but I'm not sure it's worth the overhead. I think the important thing is that we have the correct view of the world in the type checker, and I think we do.
After re-reading the available export schemes of the ES6 spec, I have a much better understanding of what is applicable and agree with you. Exporting is a commonly used language feature, so I wouldn't want to add any degradation in performance because of a spec misunderstanding.
The alternative working solution is slightly documented in the spec, but it is unclear that the word default can be used as the local import identifier name:
export {default as Foo} from './Foo';
I was however able to find a test case tracked within the traceur project doing the same. As long as there is a way to do it :)
Checked with @bterlson and he too thinks that these are illigal:
export { default } from "module2"
export { default as d } from "module2"
The spec is not really clear about these though.
Yeah... I got the idea from the import statement suggested in #2242. It seems to work appropriately.
import { default as Greeter } from "./greeter";
var g = new Greeter();
g.sayHello();
@mhegazy I was about to open a Webstorm bug which is related. Is there a different suggested way to re-export a defaulted local import?
@mtraynham i am not sure i understand the question..
here are few re-export patterns i could think of:
// module.ts
export default class {}
import d from "module";
export default d;
import {default as d } from "module";
export default d;
import {default as d } from "module";
export { d as default};
My fault if I wasn't clear. Import the default of a module and re-export with the same name as module.
Modifying what you have:
import {default as module} from "module";
export {module};
or rather:
import module from "module";
export {module};
Since you suggested that the following might be invalid:
export {default as Foo} from './Foo';
And from this bug, the following does not work:
export Foo from './Foo';
export {default as Foo} from './Foo'; should work. my bad for the false alarm.
Ahh thanks! We can close this as my question has been fully answered :)
Most helpful comment
export {default as Foo} from './Foo';should work. my bad for the false alarm.