Issue 1:
The solution suggested in #6382 doesn't work as expected. It creates false define() statements in the JavaScript file:

I believe the TypeScript compiler doesn't react correctly in regard to bundled files.

IMHO, import { module1.Identifier2, module2.Identifier1 module3.Identifier1 } from "./moduleFile" should be the only valid syntax here.

That syntax should result in loading the bundle file and import all the required modules (which I suppose should become namespaces in the generated, i.e. referenced, bundled, JavaScript file) and identifiers from there.

Issue 2:
Relates to #3089, #2743, and #17.

Goals

Bundle js emit for TS projects while preserving internal modular structure (complete with ES6 semantics and despite being concatenated into a single file), but not exposing it publicly and wrapping the chosen entrypoint with a loader for the desired external module system.

Proposal

When all of --bundle, --module and --out are specified, the TS compiler should emit a single amalgamated js file as output. --bundle is a new compiler flag, indicating that the modules used should be concatenated into the output file and loaded with a microloader at runtime. The semantics of this microloader should preserve ES6 module semantics, but may not support TS-specific ES6 module semantics, such as import a = require or exports =. This is a major point of discussion, as to if these TS-specific syntax extensions are worth continuing to support with new language features. Additionally, this should wrap the result file with --module-specific declaration wrappers, if need be.

Supporting ES6 semantics is some effort - some rewriting/moving and declaration hoisting needs to be done to support circular references between internal modules.

Most of the effort involved here involves the design of the microloader and emit for said microloader - since this is compile time, and we don't want to register any new external dependencies at runtime (with this loader), I expect we can make some optimizations compared to, say, using an internal copy of systemjs.

Additionally, we need to decide if we want to make further optimizations based on the chosen --module - if the system chosen supports asynchronous module resolution (so not commonjs), then we can potentially use a more lazy, async dependency resolver internally, too.

So, to give an example of the emit (let's say we use a system-like thing internally and are emitting a system module):

Given:

a.ts:

export * from './b';
export * from './c';

b.ts:

export interface Foo {}

export class Bar {
constructor() {
console.log('');
}

do(): Foo { throw new Error('Not implemented.'); }
}

c.ts:

export class Baz {}
export interface Foo {}

Hypothetically, with --out appLib.js, --bundle a.ts and --module system arguments, we should get something like

appLib.js:

System.register([], function (exports_1) {
var __system = /* loader code */;
//a.ts
__system.register('./a', ['./b', './c'], function(exports_1) {
function exportStar_1(m) {
var exports = {};
for(var n in m) {
if (n !== "default") exports[n] = m[n];
}
exports_1(exports);
}
return {
setters:[
function (_b_1) {
exportStar_1(_b_1);
},
function (_c_1) {
exportStar_1(_c_1);
}],
execute: function() {
}
}
});
//b.ts
__system.register('./b', [], function(exports_1) {
var Bar;
return {
setters:[],
execute: function() {
Bar = (function () {
function Bar() {
console.log('');
}
Bar.prototype.do = function () { throw new Error('Not implemented.'); };
return Bar;
})();
exports_1("Bar", Bar);
}
}
});
//c.ts
__system.register('./c', [], function(exports_1) {
var Baz;
return {
setters:[],
execute: function() {
Baz = (function () {
function Baz() {
}
return Baz;
})();
exports_1("Baz", Baz);
}
}
});

function exportStar_1(m) {
var exports = {};
for(var n in m) {
if (n !== "default") exports[n] = m[n];
}
exports_1(exports);
}
return {
setters: [],
execute: function() {
__system.import('./a').then(function (_pub_1) {
exportStar_1(_pub_1);
});
};
});