People don't understand the difference between these things:
export default class Foo {}
/* or */
class Foo {}
export = Foo;
/* or */
export class Foo { }
People also don't understand the difference between these things:
import x = require('y');
import x from 'y';
import { x } from 'y'
import * as x from 'y';
We need to write a comprehensive answer that explains which import statements correctly acquire which exports, and also describe auto-lifting behavior present in some loaders.
I've actually been trying to write this up today as part of fixing up the module bugs assigned to me. I could extract out the general info from the internal info as the basis.
Maybe I'll regret this... but feel free to assign to me if someone is not already working on it.
We should put any additional information for this in the handbook module page: https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Modules.md
we can also add a link to that page in the FAQ page.
Looks good! A couple of things that would be really useful additions:
__esModule
property and hoisting of the module.exports
to the default
property by some loaders, and our allowSyntheticDefaultImports
flag).I do not know, who is responsible for the handbook on typescriptlang.org, but the chapter "Going external" should also cover this topic, or at least a hint:
http://www.typescriptlang.org/Handbook#modules-going-external
I'd add export as namespace Foo
to this list.
+1 pls. I dont even know the answer now that finding this issue :/
TL;DR: export =
or import = require
implies the module was written as CommonJS, export default
implies it's been authored as an ECMAScript module.
export =
and import x = require('./x')
corresponds to CommonJS/AMD/etc.'s notion of module.exports
:
// ./a.js
module.exports = { a: 10, b: 20 };
// ./b.js
let a = require('./a');
A lot of the time, people will have exactly one thing that they're exporting, like a function:
// ./a.js
module.exports = function foo() { /*...*/ }
// ./b.js
var a = require('./a');
a();
export default
is a construct in ES2015 modules that is supposed to give an easy way to say "hey, here's the main thing you import from this module". ES2015 gives it a special syntax.
// a.js
export default function foo() {
// ...
}
// b.js
import a from './a.js';
a();
But it's just special syntax; really, default
is like any member on an ES2015 module record. b.js
could have been written like the following:
import * as a from './a.js';
a.default();
import { default as aFujnc } from './a.js'
aFunc();
// calculator.ts // compiled.js
// ============= // ===========
export default class Calculator { // var Calculator = /** @class */ (function () {
public add(num1, num2) { // function Calculator() {}
return num1 + num2; // Calculator.prototype.add = function (num1, num2) {
} // return num1 + num2;
} // };
// return Calculator;
// }());
// exports["default"] = Calculator;
// importer.ts // compiled.js
// =========== // ===========
import Calculator from "./calculator"; // exports.__esModule = true;
// var calculator = require("./calculator");
let calc = new Calculator(); // var calc = new calculator["default"]();
// console.log(calc.add(2, 2));
console.log(calc.add(2, 2)); //
import * as Calculator from "./calculator";
and then instantiating it using new Calculator.default()
.// calculator.ts // compiled.js
// ============= // ===========
export = class Calculator { // module.exports = /** @class */ (function () {
public add(num1, num2) { // function Calculator() {}
return num1 + num2; // Calculator.prototype.add = function (num1, num2) {
} // return num1 + num2;
} // };
// return Calculator;
// }());
// importer.ts // compiled.js
// =========== // ===========
import Calculator = require("./calculator"); // exports.__esModule = true;
// var Calculator = require("./calculator");
let calc = new Calculator(); // var calc = new Calculator();
// console.log(calc.add(2, 2));
console.log(calc.add(2, 2)); //
// calculator.ts // compiled.js
// ============= // ===========
export class Calculator { // exports.__esModule = true;
public add(num1, num2) { // var Calculator = /** @class */ (function () {
return num1 + num2; // function Calculator() {}
} // Calculator.prototype.add = function (num1, num2) {
} // return num1 + num2;
// };
// return Calculator;
// }());
// exports.Calculator = Calculator;
// importer.ts // compiled.js
// =========== // ===========
import { Calculator } from "./calculator"; // exports.__esModule = true;
// var calculator = require("./calculator");
let calc = new Calculator(); // var calc = new calculator.Calculator();
// console.log(calc.add(2, 2));
console.log(calc.add(2, 2)); //
export default ... (Default Export)
// calculator.ts // compiled.js // ============= // =========== export default class Calculator { // var Calculator = /** @class */ (function () { public add(num1, num2) { // function Calculator() {} return num1 + num2; // Calculator.prototype.add = function (num1, num2) { } // return num1 + num2; } // }; // return Calculator; // }()); // exports["default"] = Calculator;
import ... from "module";
// importer.ts // compiled.js // =========== // =========== import Calculator from "./calculator"; // exports.__esModule = true; // var calculator = require("./calculator"); let calc = new Calculator(); // var calc = new calculator["default"](); // console.log(calc.add(2, 2)); console.log(calc.add(2, 2)); //
Notes:
- A default export can be imported with any name.
- Functionally equivalent to
import * as Calculator from "./calculator";
and then instantiating it usingnew Calculator.default()
.export = ...
// calculator.ts // compiled.js // ============= // =========== export = class Calculator { // module.exports = /** @class */ (function () { public add(num1, num2) { // function Calculator() {} return num1 + num2; // Calculator.prototype.add = function (num1, num2) { } // return num1 + num2; } // }; // return Calculator; // }());
import ... = require("module");
// importer.ts // compiled.js // =========== // =========== import Calculator = require("./calculator"); // exports.__esModule = true; // var Calculator = require("./calculator"); let calc = new Calculator(); // var calc = new Calculator(); // console.log(calc.add(2, 2)); console.log(calc.add(2, 2)); //
Notes:
- This syntax is only used when importing a CommonJS module.
export ... (Named Export)
// calculator.ts // compiled.js // ============= // =========== export class Calculator { // exports.__esModule = true; public add(num1, num2) { // var Calculator = /** @class */ (function () { return num1 + num2; // function Calculator() {} } // Calculator.prototype.add = function (num1, num2) { } // return num1 + num2; // }; // return Calculator; // }()); // exports.Calculator = Calculator;
import { ... } from "module";
// importer.ts // compiled.js // =========== // =========== import { Calculator } from "./calculator"; // exports.__esModule = true; // var calculator = require("./calculator"); let calc = new Calculator(); // var calc = new calculator.Calculator(); // console.log(calc.add(2, 2)); console.log(calc.add(2, 2)); //
Notes:
- Named exports are useful to export several values.
- During the import, you must use the same name of the corresponding object.
Very helpful, thank you.
export default ... (Default Export)
// calculator.ts // compiled.js // ============= // =========== export default class Calculator { // var Calculator = /** @class */ (function () { public add(num1, num2) { // function Calculator() {} return num1 + num2; // Calculator.prototype.add = function (num1, num2) { } // return num1 + num2; } // }; // return Calculator; // }()); // exports["default"] = Calculator;
import ... from "module";
// importer.ts // compiled.js // =========== // =========== import Calculator from "./calculator"; // exports.__esModule = true; // var calculator = require("./calculator"); let calc = new Calculator(); // var calc = new calculator["default"](); // console.log(calc.add(2, 2)); console.log(calc.add(2, 2)); //
Notes:
- A default export can be imported with any name.
- Functionally equivalent to
import * as Calculator from "./calculator";
and then instantiating it usingnew Calculator.default()
.export = ...
// calculator.ts // compiled.js // ============= // =========== export = class Calculator { // module.exports = /** @class */ (function () { public add(num1, num2) { // function Calculator() {} return num1 + num2; // Calculator.prototype.add = function (num1, num2) { } // return num1 + num2; } // }; // return Calculator; // }());
import ... = require("module");
// importer.ts // compiled.js // =========== // =========== import Calculator = require("./calculator"); // exports.__esModule = true; // var Calculator = require("./calculator"); let calc = new Calculator(); // var calc = new Calculator(); // console.log(calc.add(2, 2)); console.log(calc.add(2, 2)); //
Notes:
- This syntax is only used when importing a CommonJS module.
export ... (Named Export)
// calculator.ts // compiled.js // ============= // =========== export class Calculator { // exports.__esModule = true; public add(num1, num2) { // var Calculator = /** @class */ (function () { return num1 + num2; // function Calculator() {} } // Calculator.prototype.add = function (num1, num2) { } // return num1 + num2; // }; // return Calculator; // }()); // exports.Calculator = Calculator;
import { ... } from "module";
// importer.ts // compiled.js // =========== // =========== import { Calculator } from "./calculator"; // exports.__esModule = true; // var calculator = require("./calculator"); let calc = new Calculator(); // var calc = new calculator.Calculator(); // console.log(calc.add(2, 2)); console.log(calc.add(2, 2)); //
Notes:
- Named exports are useful to export several values.
- During the import, you must use the same name of the corresponding object.
Very helpful, thank you.
import = require does not work for me
// calculator.ts
// =============
export class Calculator {
public add(num1, num2) {
return num1 + num2;
}
}
import { Calculator } from "./calculator";
let calc = new Calculator();
console.log(calc.add(2, 2));
This is most likely the wrong forum for your issue. I would suggest either Stack Overflow or creating a new issue.
I've been using TS for over a year and I'm still confused about the below. I've thrown it on stackoverflow but I bet it'll be helpful for this documentation as well.
/// file1
export {
PORT,
SSL_CRT,
SSL_KEY,
}
// file2
import * as env from 'file1'
export {
...env // [ts] Identifier expected. [1003]
}
md5-d5dff0d160b3a11babed7b7d596f57e3
// file2
import * as env from 'file1'
export default {
...env // [ts] Identifier expected. [1003]
}
Most helpful comment
export default ... (Default Export)
import ... from "module";
Notes:
import * as Calculator from "./calculator";
and then instantiating it usingnew Calculator.default()
.export = ...
import ... = require("module");
Notes:
export ... (Named Export)
import { ... } from "module";
Notes: