4

Are the three export options exactly equivalent?

// foo.ts
export const foo = () => {}
// foo.ts
const foo = () => {}
export default { foo }
// foo.ts
const foo = () => {}
export { foo }

Disclaimer: I know that import { foo } from './foo' will work just the same in all scenarios but are there any nuances?

Particularly interested in any nuances that might occur when having a mixed ts and js codebase.

Using tsconfig "module": "CommonJS", nodejs v14 and typescript 4.2.4

6
  • Are you using CommonJS or ES6? Commented Aug 2, 2021 at 17:34
  • I take it you're using a bundler of some kind? Since that isn't CommonJS syntax. Commented Aug 2, 2021 at 17:54
  • Using tsc locally and then esbuild for prod. Commented Aug 2, 2021 at 17:55
  • 5
    I can't speak to TypeScript's handling of this stuff, so I won't post an answer. But beware that in the standard module syntax defined by the JavaScript specification, the second of those three does a very different thing to the other two (the first and third are exactly equivalent). It may be that TypeScript lets you import all three the same way, but if so that's a TypeScript thing. In standard ESM, your first and third blocks create a named export you'd import as import { foo } from "./mod.js"; Your ... Commented Aug 2, 2021 at 17:59
  • 5
    ...second block creates a default export of an object with a foo property (which is very different from a named export), which you cannot import using named import syntax. Instead, you'd import the default (import obj from "./foo.js";) and either destructure foo from it (const { foo } = obj;) or just use it as obj.foo. That one is not constant; code in modules using it can change the value of foo via simple assignment. The single exported object is shared by all modules. Commented Aug 2, 2021 at 18:00

1 Answer 1

3

The short answer is no they're not the same, they have different syntax, but let's be serious.

export const foo = () => {}

...

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.foo = void 0;
var foo = function () { };
exports.foo = foo;

Is what that compiles to using commonjs and es5 as target.

const foo = () => {}
export default { foo }

...

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var foo = function () { };
exports.default = { foo: foo };

Is what that compiles to.

const foo = () => {}
export { foo }

...

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.foo = void 0;
var foo = function () { };
exports.foo = foo;

Is what that compiles to.

Along with that it should also be noted that using:

export { foo }

Can only be imported using:

import {foo} from './foo'

While using:

export default { foo }

Can only be imported using:

import whatever from './foo'

// use whatever.foo
Sign up to request clarification or add additional context in comments.

2 Comments

import {foo} from './foo' should not work with a default export.
Ah, so I shouldn't have believed the part of the question where the OP said TypeScript allowed using named import syntax with the default export of the object. You should explain what whatever ends up being in that case, since it's different.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.