-
-
Notifications
You must be signed in to change notification settings - Fork 5.8k
Description
💻
- Would you like to work on a fix?
How are you using Babel?
Programmatic API (babel.transform, babel.parse)
Input code
export default interface {}Configuration file name
No response
Configuration
{
"presets": ["@babel/preset-typescript"]
}Current and expected behavior
Current: Parsed incorrectly as an ExportDeclaration with ObjectExpression.
Expected: Babel should throw an identifier is expected after interface, aligning to TSC behaviour: TS Playground
Environment
REPL
Possible solution
Babel parser handles export default interface {} in
babel/packages/babel-parser/src/plugins/typescript/index.js
Lines 1801 to 1803 in e0dc925
| if (this.tsCheckLineTerminator(next) && this.match(tt.name)) { | |
| return this.tsParseInterfaceDeclaration(node); | |
| } |
The tsCheckLineTerminator eats interface but then since parser doesn't see a tt.name (identifier token) following, it exits without rewinding the parser states so the source is parsed as if it were export default {}.
We can perform lookahead after interface and see if it is a tt.name in
babel/packages/babel-parser/src/plugins/typescript/index.js
Lines 2307 to 2315 in e0dc925
| if (this.state.value === "interface") { | |
| const result = this.tsParseDeclaration( | |
| this.startNode(), | |
| this.state.value, | |
| true, | |
| ); | |
| if (result) return result; | |
| } |
like how we handle export default abstract class:
babel/packages/babel-parser/src/plugins/typescript/index.js
Lines 2290 to 2294 in e0dc925
| isAbstractClass(): boolean { | |
| return ( | |
| this.isContextual("abstract") && this.lookahead().type === tt._class | |
| ); | |
| } |
Additional context
No response