-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
TypeScript Version: nightly (2.2.0-dev.20161127)
EDIT: The issue described below is with --module commonjs, but as @aluanhaddad points out in a comment below, there are other behaviours with different module emits.
I looked for an existing issue about this but didn't find one. Apologies if this is a duplicate.
I ran into a problem with TypeScript's emit for re-exported bindings, in particular when the original exported value changes over time.
Importing a binding directly from a source module gets a 'live view' that changes when the export value changes, as it should. But importing from a re-exported binding gets a snapshot that is no longer a live view of the original export. This seems not to be spec compliant and leads to my code not working as intended.
Code
// file: a.ts
export let liveView = 'foo';
export function changeTo(val: string) { liveView = val; } // CHANGES THE EXPORT VALUE
// file: b.ts
import {liveView, changeTo} from './a'; // <===== Import directly from A
console.log(liveView); // outputs 'foo'
changeTo('bar');
console.log(liveView); // outputs 'bar' <===== GOOD: binding changed as it should
export {liveView, changeTo} from './a'; // <===== Re-export from A
// file: c.ts
import {liveView, changeTo} from './b'; // <===== Import via B's re-export
console.log(liveView); // outputs 'bar'
changeTo('baz');
console.log(liveView); // outputs 'bar' // <===== BAD: binding is not live anymoreExpected behavior
Emitted code should preserve the live binding to liveView when re-exporting from b.ts.
Last line of c.ts should output 'baz'.
Actual behavior
Emitted code exports a 'snapshot' of the liveView binding from b.ts, so that the import of liveView into c.ts is no longer a live binding.
Last line of c.ts incorrectly outputs 'bar'.
What should be the Correct Behaviour?
I found it hard to locate a clear description of correct ES6 behaviour for this situation, but from what I did find I think TypeScript's current emit is not compliant with ES6.
-
E.g. from the Exploring ES6 sections about imports as views and about re-exports
-
Babel emits code that preserves the 'live-ness' of re-exports
So for export { liveView } from 'some-module'; TypeScript emits something like:
var some_module_1 = require("some-module");
exports.liveView = some_module_1.liveView;Whereas babel emits something like:
var _someModule = require('some-module');
Object.defineProperty(exports, 'liveView', {
enumerable: true,
get: function get() {
return _someModule.liveView;
}
});