Skip to content

[Bug] Re-exported binding doesn't track the original binding #12522

Closed
@yortus

Description

@yortus

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 anymore

Expected 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.

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;
  }
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    Breaking ChangeWould introduce errors in existing codeBugA bug in TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions