Skip to content

The export default interface is allowed with verbatimModuleSyntax enabled #57518

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

Closed
ueokande opened this issue Feb 24, 2024 · 8 comments
Closed
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@ueokande
Copy link

πŸ”Ž Search Terms

  • verbatimModuleSyntax
  • export default interface

πŸ•— Version & Regression Information

  • I can reproduce on v5.0.4 and the nightly version.

⏯ Playground Link

https://www.typescriptlang.org/play?target=99&noImplicitReturns=false&alwaysStrict=false&noImplicitThis=false&strictPropertyInitialization=false&strictBindCallApply=false&strictFunctionTypes=false&strictNullChecks=false&noImplicitAny=false&ts=5.5.0-dev.20240224&esModuleInterop=false&declaration=false&jsx=0&verbatimModuleSyntax=true&allowSyntheticDefaultImports=false#code/KYDwDg9gTgLgBAE2AMwIYFcA28CWA7GYKNAY2DgEk4BvAXyA

πŸ’» Code

export default interface I {}

πŸ™ Actual behavior

The compiler allows export default interface I {} with verbatimModuleSyntax enabled.

πŸ™‚ Expected behavior

When we try to export an interface separately with the definition and export default syntax, the tsc outputs an error.

interface I {}
export default I
An 'export default' must reference a value when 'verbatimModuleSyntax' is enabled, but 'I' only refers to a type.

We can export an interface with export default interface I {...} even if the exported name does not reference a value, it references an interface. I have no idea whether the tsc should output an error in that case since I cannot found such case in the test. I think it can either be an error or needs to update the error message.

Additional information about the issue

No response

@whzx5byb
Copy link

whzx5byb commented Feb 25, 2024

Related: #41409

Maybe it's just because we don't have the export default type symbol?

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Feb 25, 2024
@ueokande
Copy link
Author

I'm not sure. But by the error message, I guess, the compiler expects that the exported symbol is a value. I think the tsc should output an error if we could use export default type.

@andrewbranch andrewbranch added Bug A bug in TypeScript Help Wanted You can do this and removed Needs Investigation This issue needs a team member to investigate its status. labels Feb 26, 2024
@andrewbranch andrewbranch added this to the TypeScript 5.5.0 milestone Feb 26, 2024
@andrewbranch andrewbranch added Working as Intended The behavior described is the intended behavior; this is not a bug and removed Help Wanted You can do this Bug A bug in TypeScript labels Mar 28, 2024
@andrewbranch andrewbranch removed this from the TypeScript 5.5.0 milestone Mar 28, 2024
@andrewbranch andrewbranch removed their assignment Mar 28, 2024
@andrewbranch
Copy link
Member

This is a bit subtle, but it’s working as designed. The goal with verbatimModuleSyntax is to ensure that all module-related valid JavaScript code gets emitted as-is. export default I is a valid JavaScript statement, so we enforce that it can be emitted as-is without causing errors. On the other hand, export default interface I {} is not valid JavaScript; it’s TypeScript-only code that happens to have export default modifiers on it, which sometimes also appear in valid JavaScript code. It’s allowed for the same reason that export interface I {} is allowed. What matters is what kind of statement the top-level thing is. Even though export default I and export default interface I {} have the same effect, the former is an ECMAScript-defined ExportDeclaration, while the latter is a TypeScript InterfaceDeclaration.

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 31, 2024
@ajmas
Copy link

ajmas commented Apr 3, 2024

It is not clear in that case what the 'correct' way of dealing with this is?

If I follow a 'one interface declaration' by file approach:

interface IMyInterface { 
  // interface props
}

Then none of these work:

export default IMyInterface;
export IMyInterface;
export { IMyInterface };
export default type IMediaItem;

I feel like I am forced to use the verbatimModuleSyntax, simply because there isn't a clear 'correct' solution. At least the TS error 1284, doesn't provide sufficient clues.

BTW If I can track down an answer, I'll provide it here.

@andrewbranch
Copy link
Member

export default interface IMyInterface {
  // interface props
}

and

interface IMyInterface {
  // interface props
}
export type { IMyInterface as default };

are two verbatimModuleSyntax-compatible ways of default-exporting an interface.

@rauschma
Copy link

Given that this works:

export default interface Intf {}

Shouldn’t either one of the following work too? Why should interfaces get special syntactic treatment?

export default type MyType = {};
export default type SomeOtherType;

@andrewbranch
Copy link
Member

I’m guessing because interface is a reserved word in ECMAScript whereas type is not. Both of those constructions would need ASI restrictions:

export default type
MyType = {};

export default type
SomeOtherType;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

7 participants