-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Fix source type detection when parsing TypeScript #17107
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
Fix source type detection when parsing TypeScript #17107
Conversation
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/58671 |
@@ -2374,6 +2364,10 @@ export default abstract class StatementParser extends ExpressionParser { | |||
} | |||
this.parseExportFrom(node, true); | |||
|
|||
if (node.exportKind !== "type") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is one thing typescript-eslint differs: they set the sourceType
to module
even when the source only includes type imports/exports: AFAIK TS does not offer ways to include types via commonJS require, so I am not convinced that we should do so as well. To align with their AST we can monkey patch the eslint-parser instead.
@bradzacher Could you shred some light here? Thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually entirely correct to treat the file as a module if it only contains only type-only import -- it's the same behaviour that TS itself exhibits.
For example you can see in this playground.
- the emitted JS code is
export {};
- there is no error on the
Map
interface (see below)
But if you comment out the type-only import then:
- the emitted JS code is instead
"use strict";
as it's no longer treated as an ESM file - there is an error on the
Map
interface as TS is trying to declaration merge with the global type.
So yeah -- our behaviour is aligned with TS itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK TS does not offer ways to include types via commonJS require
It does, but not in the same "type only" fashion.
// module.ts
namespace Foo {
export type T = number;
}
export = Foo;
// other.ts
import Foo = require('./module');
type T = Foo.T;
It's much more cumbersome, but still valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bradzacher Thank you for your detailed explanation, from which I have learned a lot. In that case I think we will align to TS as well.
@@ -4,7 +4,7 @@ | |||
"program": { | |||
"type": "Program", | |||
"start":0,"end":78,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":3,"column":25,"index":78}}, | |||
"sourceType": "script", | |||
"sourceType": "module", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR also changes the flow handling. As we can see from the playground, both
import react from "react";
const yield = 1;
and
import type react from "react";
const yield = 1;
are accepted, which means flow does not set the script type based on imports. So we already deviated from the flow behaviour for non-type imports.
* add new test cases * fix: move sawUnambiguousESM to parseExport * fix: set sawUnambiguousESM on type imports * update test fixtures
export { a }
withtypescript
plugin andunambiguous
source type does not set program sourceType tomodule
(part of #16679)This issue surfaces when we are aligning to the typescript-eslint AST. The typescript parser plugin called
super.parseExport
without handling thesawUnambiguousESM
state, here we moved the state handling intoparseExport
so it should work for both JS and TS.