1

I can define a function and then export as default, define it an export it inline, or define it and export it as default inline:

function myFunc() {
    ...
}
export default myFunc;
export function myFunc2() {
    ...
}
export default function myFunc3(param) {
    ...
}

I can define a class and then export as default, define it and export it inline, or define it and export it as default inline:

class MyClass {
    ...
}
export default MyClass;
export class MyClass2 {
    ...
}
export default class MyClass3 {
    ...
}

Cool, so classes and functions are consistent. Now, constants:

Define and then export as default:

const myConst = 42;
export default myConst;

Define and export inline:

export const myConst = 42;

Those are fine. But I cannot define it and export as default inline:

export default const myConst = 42; // nope -- syntax error!

My question: why are constants different than classes and functions in this regard? They're all exportable, all exportable as defaults. Why can't I do it inline with a constant?

I found Why Is `Export Default Const` invalid? while googling. I believe the asker was trying to ask the same question I am, but there is a highly upvoted, accepted answer which does not answer my question. I am not asking for the technical reason the compiler rejects the syntax. I am looking to understand why the language is designed this way.

If it helps, the answer might take the form of "if this syntax were supported, [thing] would happen," or "it used to work that way, but we removed it because [thing] happened," or "there's an open discussion on adding this to the spec, see [here]."

If the distinction between TypeScript and JavaScript is in any way relevant to the answer, please clarify.

JakeRobb
  • 1,711
  • 1
  • 17
  • 32
  • 3
    `I am looking to understand why the language is designed this way.` Few of us designed the language, so you may have a tough time getting a satisfactory answer. – Nicholas Tower Mar 18 '21 at 21:34
  • @NicholasTower I don't have a problem with that. :) – JakeRobb Mar 18 '21 at 21:35
  • 3
    Because you don’t need to. A default export isn’t named by definition, you can just `export default 42;`. – jonrsharpe Mar 18 '21 at 21:37
  • Maybe it can help a little bit - https://stackoverflow.com/questions/36261225/why-is-export-default-const-invalid – Kishieel Mar 18 '21 at 21:39
  • I feel like that other question you referenced discusses this about as in-depth as the discussion is going to get. Not sure what else you're looking for in an answer – Seth Lutske Mar 18 '21 at 21:41
  • After reading that other question you referenced, I think that you are wondering and asking *why* `default` does not accept a *LexicalDeclaration*. Is that correct? Interesting question. Sadly I cannot answer it, since I don't have a clue. – Bart Hofland Mar 18 '21 at 21:47
  • @TomaszKisiel I linked that question in my question and explained why it doesn't help. – JakeRobb Mar 19 '21 at 02:54
  • @BartHofland that question is still too deep in the weeds of the grammar. Presumably this is done on purpose; why wouldn't the language designers want the language to support this syntax? – JakeRobb Mar 19 '21 at 02:56

2 Answers2

2

I just scanned through Why is "export default var a = 1;" invalid syntax? at ES Discuss. After doing so, it seems to me that it has something to do with the differences in the nature of the concepts of binding declarations and default exports.

You can declare multiple bindings in one statement like this:

const a = 1, b = 2, c = 3;

But the default export has to be just a single expression. Therefore, the concepts of declarations and default exports cannot be matched in a logical sense, so trying to combine them in a one-liner just cannot be done syntactically. It cannot be determined what the default export in the following statement should be:

export default const a = 1, b = 2, c = 3;

Functions and classes do not have these issues. You cannot declare multiple functions or classes in a single statement like you can with bindings/variables. So functions and classes can be declared as default exports in a one-liner.

Bart Hofland
  • 3,700
  • 1
  • 13
  • 22
  • This seems like it would be easy enough to work around at the language level if the designers wanted. You simply create a syntax that only allows one expression for use with `export default`. – JakeRobb Mar 19 '21 at 15:40
1

Have a look at why JavaScript has default exports at all. They were introduced as syntactic sugar:

export default function example() {}
// is the same as
function example() {}
export { example as default }
export default class Example {}
// is the same as
class Example {}
export { Example as default }
export default (expression);
// is the same as
let *default* = (expression);
export { *default* as default }

export is not a modifier you can slap onto any declaration, it is a separate kind of declaration statement.

Default exports/imports are meant to simplify the common use case of a module exporting a single function or class, under an insignificant name (that's why they even allow anonymous declarations) - large entities for which it makes sense to create an entire module (or just following the Java "one file per class" pattern). A constant value is not something you'd generally create an own module for, so it got no special syntactic sugar. Go with

const myConst = 42;
export { myConst as default};

or (if you don't actually need the local name)

export default 42;
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • `42` was a contrived example. It's common to declare much more complex things as constants -- for example, anonymous functions. `const func = (some args) => { some impl }`. Why shouldn't I be able to `export default` that inline? – JakeRobb Mar 19 '21 at 03:00
  • 1
    @JakeRobb If you wanted it anonymous, you'd just write `export default (some args) => { some impl }`. If you wanted it named, you could as well use a function declaration `export default function func(some args) { some impl }`. There's not many cases where you have to declare a `const` (next to other things in the module) and also want it become the default export. At least that is how it was designed - I'm not saying it fits to all programming styles :-) – Bergi Mar 19 '21 at 03:26
  • Right, I understand that there are alternative equivalent syntaxes. I'm asking why this one particular syntax, which seems to extend naturally/logically from the ones available for functions and classes isn't available for constants. – JakeRobb Mar 19 '21 at 15:42