Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

export declare sometimes affects JS emit #60932

Open
nicolo-ribaudo opened this issue Jan 8, 2025 · 4 comments
Open

export declare sometimes affects JS emit #60932

nicolo-ribaudo opened this issue Jan 8, 2025 · 4 comments
Labels
Bug A bug in TypeScript Help Wanted You can do this
Milestone

Comments

@nicolo-ribaudo
Copy link

nicolo-ribaudo commented Jan 8, 2025

πŸ”Ž Search Terms

export declare js emit

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried

⏯ Playground Link

https://www.typescriptlang.org/play/?module=1#code/KYDwDg9gTgLgBAE2AYwDYEMrDq490BccAdgK4C2ARsFANwBQ6cAvHAEwNA

πŸ’» Code

export declare let a: number;
a = 2;

πŸ™ Actual behavior

When compiled to JS, will that code export a variable named a? It depends!

  • if compiling to ESM, no
  • if compiling to CJS/AMD, yes
  • if inside a namespace, yes

πŸ™‚ Expected behavior

Compiling to ESM or to CJS/AMD should behave the same. Specifically, they should all have the ESM behavior (no a exported), since declare means "this statement is only to tell something to the type checker, it should not actually affect the emitted JS code".

Maybe referencing locally something declared as export declare should be an error.

Additional information about the issue

Babel (babel/babel#17038), SWC (swc-project/swc#9821), and OXC (https://playground.oxc.rs/#eNo9TjFuwzAM/IrA2UNToIuKrp37gC60QgcGJFIg5TSB4b+XiuNo0R15d7wVEkRgLGQVEwW2sP5y8Ee3KtrCmVJGpZCpBYyBlzKSfu4SDF/h5HiDAQTiCrpw/+zODW8Qmy40QJ65QZwwmxNLUunY2L2Mkg/WFNkm0bIPtgEqqpH2xKrk6Eo/XoXtmeaKnv1QOH75d0tDvZAfBrL3t9MHuCLJmS7UKzopM8/TfJiTcFPJ31n+uvlKOop50f3Qtv0D8iJmOg==) already have the behavior I'm proposing.

@robpalme
Copy link

robpalme commented Jan 8, 2025

FYI ESBuild consciously chose to match current tsc behavior.

@nicolo-ribaudo
Copy link
Author

ESBuild only matches tsc when it comes to export declare inside namespace, and not for export declare when targeting CJS: https://esbuild.egoist.dev/#W1siaW5kZXgudHMiLHsiY29udGVudCI6ImV4cG9ydCBkZWNsYXJlIGxldCBhOiBudW1iZXI7XG5hID0gMjsifV0sWyJlc2J1aWxkLmNvbmZpZy5qc29uIix7ImNvbnRlbnQiOiJ7XG4gIFwiZm9ybWF0XCI6IFwiY2pzXCIsXG4gIFwiY2RuVXJsXCI6IFwiaHR0cHM6Ly9lc20uc2hcIlxufSJ9XV0=

@RyanCavanaugh RyanCavanaugh added Bug A bug in TypeScript Help Wanted You can do this labels Jan 8, 2025
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Jan 8, 2025
@Andarist
Copy link
Contributor

Andarist commented Jan 9, 2025

export declare... what that even is supposed to mean? πŸ˜… The non-ESM module transforms emit this based on the logic in substituteExpressionIdentifier (that calls into resolver.getReferencedExportContainer, which returns exportContainer.kind === SyntaxKind.SourceFile). This is something that's recorded as an export of that source file, so it seems to be "available" as an export/import.

When this is imported by other modules the emit for them includes appropriate importing statements:

@RyanCavanaugh could you clarify what the expected behavior here is?

@RyanCavanaugh
Copy link
Member

export declare is indeed extremely confusing. I think the best interpretation is effectively "Pretend that someone text-concats an equivalent real export declaration somewhere in this file", which is load-bearing on "equivalent"

Looking at the emit again, I'm not super sure what the defect is actually supposed to be.

For CJS we have

exports.a = 2;

which is a correct output; it's the same as if you wrote

export let a: number = 3;
a = 2;

which produces

exports.a = 3;
exports.a = 2;

so we're exactly corresponding to the second line

For ESM we have

a = 2;

which is correct according to the "pretend that someone text-concated" interpretation of export declare

Absent a stronger argument, this is maybe just working as intended?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Help Wanted You can do this
Projects
None yet
Development

No branches or pull requests

4 participants