diff --git a/packages/babel-generator/src/generators/modules.ts b/packages/babel-generator/src/generators/modules.ts index f95533a38acc..16cd4bd08aef 100644 --- a/packages/babel-generator/src/generators/modules.ts +++ b/packages/babel-generator/src/generators/modules.ts @@ -40,6 +40,11 @@ export function ExportDefaultSpecifier( } export function ExportSpecifier(this: Printer, node: t.ExportSpecifier) { + if (node.exportKind === "type") { + this.word("type"); + this.space(); + } + this.print(node.local, node); // @ts-expect-error todo(flow-ts) maybe check node type instead of relying on name to be undefined on t.StringLiteral if (node.exported && node.local.name !== node.exported.name) { diff --git a/packages/babel-generator/test/fixtures/typescript/type-only-export-specifier/input.js b/packages/babel-generator/test/fixtures/typescript/type-only-export-specifier/input.js new file mode 100644 index 000000000000..96fce1593f9e --- /dev/null +++ b/packages/babel-generator/test/fixtures/typescript/type-only-export-specifier/input.js @@ -0,0 +1 @@ +export { type foo } from "foo"; diff --git a/packages/babel-generator/test/fixtures/typescript/type-only-export-specifier/output.js b/packages/babel-generator/test/fixtures/typescript/type-only-export-specifier/output.js new file mode 100644 index 000000000000..fd80c0978c69 --- /dev/null +++ b/packages/babel-generator/test/fixtures/typescript/type-only-export-specifier/output.js @@ -0,0 +1 @@ +export { type foo } from "foo"; \ No newline at end of file diff --git a/packages/babel-generator/test/fixtures/typescript/type-only-import-specifier/input.js b/packages/babel-generator/test/fixtures/typescript/type-only-import-specifier/input.js new file mode 100644 index 000000000000..46ea4b7e00c5 --- /dev/null +++ b/packages/babel-generator/test/fixtures/typescript/type-only-import-specifier/input.js @@ -0,0 +1 @@ +import { type foo } from "foo"; diff --git a/packages/babel-generator/test/fixtures/typescript/type-only-import-specifier/output.js b/packages/babel-generator/test/fixtures/typescript/type-only-import-specifier/output.js new file mode 100644 index 000000000000..5805ddf6cba4 --- /dev/null +++ b/packages/babel-generator/test/fixtures/typescript/type-only-import-specifier/output.js @@ -0,0 +1 @@ +import { type foo } from "foo"; \ No newline at end of file diff --git a/packages/babel-parser/src/parser/statement.js b/packages/babel-parser/src/parser/statement.js index fe76988e8da8..1170a7a9cc77 100644 --- a/packages/babel-parser/src/parser/statement.js +++ b/packages/babel-parser/src/parser/statement.js @@ -1878,7 +1878,8 @@ export default class StatementParser extends ExpressionParser { maybeParseExportNamedSpecifiers(node: N.Node): boolean { if (this.match(tt.braceL)) { if (!node.specifiers) node.specifiers = []; - node.specifiers.push(...this.parseExportSpecifiers()); + const isTypeExport = node.exportKind === "type"; + node.specifiers.push(...this.parseExportSpecifiers(isTypeExport)); node.source = null; node.declaration = null; @@ -2158,7 +2159,7 @@ export default class StatementParser extends ExpressionParser { // Parses a comma-separated list of module exports. - parseExportSpecifiers(): Array { + parseExportSpecifiers(isInTypeExport: boolean): Array { const nodes = []; let first = true; @@ -2172,24 +2173,41 @@ export default class StatementParser extends ExpressionParser { this.expect(tt.comma); if (this.eat(tt.braceR)) break; } - - const node = this.startNode(); + const isMaybeTypeOnly = this.isContextual(tt._type); const isString = this.match(tt.string); - const local = this.parseModuleExportName(); - node.local = local; - if (this.eatContextual(tt._as)) { - node.exported = this.parseModuleExportName(); - } else if (isString) { - node.exported = cloneStringLiteral(local); - } else { - node.exported = cloneIdentifier(local); - } - nodes.push(this.finishNode(node, "ExportSpecifier")); + const node = this.startNode(); + node.local = this.parseModuleExportName(); + nodes.push( + this.parseExportSpecifier( + node, + isString, + isInTypeExport, + isMaybeTypeOnly, + ), + ); } return nodes; } + parseExportSpecifier( + node: any, + isString: boolean, + /* eslint-disable no-unused-vars -- used in TypeScript parser */ + isInTypeExport: boolean, + isMaybeTypeOnly: boolean, + /* eslint-enable no-unused-vars */ + ): N.ExportSpecifier { + if (this.eatContextual(tt._as)) { + node.exported = this.parseModuleExportName(); + } else if (isString) { + node.exported = cloneStringLiteral(node.local); + } else if (!node.exported) { + node.exported = cloneIdentifier(node.local); + } + return this.finishNode(node, "ExportSpecifier"); + } + // https://tc39.es/ecma262/#prod-ModuleExportName parseModuleExportName(): N.StringLiteral | N.Identifier { if (this.match(tt.string)) { @@ -2438,15 +2456,29 @@ export default class StatementParser extends ExpressionParser { if (this.eat(tt.braceR)) break; } - this.parseImportSpecifier(node); + const specifier = this.startNode(); + const importedIsString = this.match(tt.string); + const isMaybeTypeOnly = this.isContextual(tt._type); + specifier.imported = this.parseModuleExportName(); + const importSpecifier = this.parseImportSpecifier( + specifier, + importedIsString, + node.importKind === "type" || node.importKind === "typeof", + isMaybeTypeOnly, + ); + node.specifiers.push(importSpecifier); } } // https://tc39.es/ecma262/#prod-ImportSpecifier - parseImportSpecifier(node: N.ImportDeclaration): void { - const specifier = this.startNode(); - const importedIsString = this.match(tt.string); - specifier.imported = this.parseModuleExportName(); + parseImportSpecifier( + specifier: any, + importedIsString: boolean, + /* eslint-disable no-unused-vars -- used in TypeScript and Flow parser */ + isInTypeOnlyImport: boolean, + isMaybeTypeOnly: boolean, + /* eslint-enable no-unused-vars */ + ): N.ImportSpecifier { if (this.eatContextual(tt._as)) { specifier.local = this.parseIdentifier(); } else { @@ -2459,10 +2491,12 @@ export default class StatementParser extends ExpressionParser { ); } this.checkReservedWord(imported.name, specifier.start, true, true); - specifier.local = cloneIdentifier(imported); + if (!specifier.local) { + specifier.local = cloneIdentifier(imported); + } } this.checkLVal(specifier.local, "import specifier", BIND_LEXICAL); - node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); + return this.finishNode(specifier, "ImportSpecifier"); } // This is used in flow and typescript plugin diff --git a/packages/babel-parser/src/plugins/flow/index.js b/packages/babel-parser/src/plugins/flow/index.js index 666a33c3a7fb..fc915fe1dfe6 100644 --- a/packages/babel-parser/src/plugins/flow/index.js +++ b/packages/babel-parser/src/plugins/flow/index.js @@ -2123,7 +2123,9 @@ export default (superClass: Class): Class => if (this.match(tt.braceL)) { // export type { foo, bar }; - node.specifiers = this.parseExportSpecifiers(); + node.specifiers = this.parseExportSpecifiers( + /* isInTypeExport */ true, + ); this.parseExportFrom(node); return null; } else { @@ -2629,10 +2631,14 @@ export default (superClass: Class): Class => } // parse import-type/typeof shorthand - parseImportSpecifier(node: N.ImportDeclaration): void { - const specifier = this.startNode(); - const firstIdentIsString = this.match(tt.string); - const firstIdent = this.parseModuleExportName(); + parseImportSpecifier( + specifier: any, + importedIsString: boolean, + isInTypeOnlyImport: boolean, + // eslint-disable-next-line no-unused-vars + isMaybeTypeOnly: boolean, + ): N.ImportSpecifier { + const firstIdent = specifier.imported; let specifierTypeKind = null; if (firstIdent.type === "Identifier") { @@ -2669,7 +2675,7 @@ export default (superClass: Class): Class => specifier.imported = this.parseIdentifier(true); specifier.importKind = specifierTypeKind; } else { - if (firstIdentIsString) { + if (importedIsString) { /*:: invariant(firstIdent instanceof N.StringLiteral) */ throw this.raise( specifier.start, @@ -2690,17 +2696,16 @@ export default (superClass: Class): Class => } } - const nodeIsTypeImport = hasTypeImportKind(node); const specifierIsTypeImport = hasTypeImportKind(specifier); - if (nodeIsTypeImport && specifierIsTypeImport) { + if (isInTypeOnlyImport && specifierIsTypeImport) { this.raise( specifier.start, FlowErrors.ImportTypeShorthandOnlyInPureImport, ); } - if (nodeIsTypeImport || specifierIsTypeImport) { + if (isInTypeOnlyImport || specifierIsTypeImport) { this.checkReservedType( specifier.local.name, specifier.local.start, @@ -2708,7 +2713,7 @@ export default (superClass: Class): Class => ); } - if (isBinding && !nodeIsTypeImport && !specifierIsTypeImport) { + if (isBinding && !isInTypeOnlyImport && !specifierIsTypeImport) { this.checkReservedWord( specifier.local.name, specifier.start, @@ -2718,7 +2723,7 @@ export default (superClass: Class): Class => } this.checkLVal(specifier.local, "import specifier", BIND_LEXICAL); - node.specifiers.push(this.finishNode(specifier, "ImportSpecifier")); + return this.finishNode(specifier, "ImportSpecifier"); } parseBindingAtom(): N.Pattern { diff --git a/packages/babel-parser/src/plugins/typescript/index.js b/packages/babel-parser/src/plugins/typescript/index.js index 8dc67d9d73bb..4f1705b9c4bc 100644 --- a/packages/babel-parser/src/plugins/typescript/index.js +++ b/packages/babel-parser/src/plugins/typescript/index.js @@ -11,6 +11,7 @@ import { tokenIsTSDeclarationStart, tokenIsTSTypeOperator, tokenOperatorPrecedence, + tokenIsKeywordOrIdentifier, tt, type TokenType, } from "../../tokenizer/types"; @@ -41,6 +42,7 @@ import { type ErrorTemplate, ErrorCodes, } from "../../parser/error"; +import { cloneIdentifier } from "../../parser/node"; type TsModifier = | "readonly" @@ -151,6 +153,10 @@ const TSErrors = makeErrorTemplates( "Type annotations must come before default assignments, e.g. instead of `age = 25: number` use `age: number = 25`.", TypeImportCannotSpecifyDefaultAndNamed: "A type-only import can specify a default import or named bindings, but not both.", + TypeModifierIsUsedInTypeExports: + "The 'type' modifier cannot be used on a named export when 'export type' is used on its export statement.", + TypeModifierIsUsedInTypeImports: + "The 'type' modifier cannot be used on a named import when 'import type' is used on its import statement.", UnexpectedParameterModifier: "A parameter property is only allowed in a constructor implementation.", UnexpectedReadonly: @@ -3368,4 +3374,130 @@ export default (superClass: Class): Class => } return super.getExpression(); } + + parseExportSpecifier( + node: any, + isString: boolean, + isInTypeExport: boolean, + isMaybeTypeOnly: boolean, + ) { + if (!isString && isMaybeTypeOnly) { + this.parseTypeOnlyImportExportSpecifier( + node, + /* isImport */ false, + isInTypeExport, + ); + return this.finishNode(node, "ExportSpecifier"); + } + node.exportKind = "value"; + return super.parseExportSpecifier( + node, + isString, + isInTypeExport, + isMaybeTypeOnly, + ); + } + + parseImportSpecifier( + specifier: any, + importedIsString: boolean, + isInTypeOnlyImport: boolean, + isMaybeTypeOnly: boolean, + ): N.ImportSpecifier { + if (!importedIsString && isMaybeTypeOnly) { + this.parseTypeOnlyImportExportSpecifier( + specifier, + /* isImport */ true, + isInTypeOnlyImport, + ); + return this.finishNode(specifier, "ImportSpecifier"); + } + specifier.importKind = "value"; + return super.parseImportSpecifier( + specifier, + importedIsString, + isInTypeOnlyImport, + isMaybeTypeOnly, + ); + } + + parseTypeOnlyImportExportSpecifier( + node: any, + isImport: boolean, + isInTypeOnlyImportExport: boolean, + ): void { + const leftOfAsKey = isImport ? "imported" : "local"; + const rightOfAsKey = isImport ? "local" : "exported"; + + let leftOfAs = node[leftOfAsKey]; + let rightOfAs; + + let hasTypeSpecifier = false; + let canParseAsKeyword = true; + + const pos = leftOfAs.start; + + // https://github.com/microsoft/TypeScript/blob/fc4f9d83d5939047aa6bb2a43965c6e9bbfbc35b/src/compiler/parser.ts#L7411-L7456 + // import { type } from "mod"; - hasTypeSpecifier: false, leftOfAs: type + // import { type as } from "mod"; - hasTypeSpecifier: true, leftOfAs: as + // import { type as as } from "mod"; - hasTypeSpecifier: false, leftOfAs: type, rightOfAs: as + // import { type as as as } from "mod"; - hasTypeSpecifier: true, leftOfAs: as, rightOfAs: as + if (this.isContextual(tt._as)) { + // { type as ...? } + const firstAs = this.parseIdentifier(); + if (this.isContextual(tt._as)) { + // { type as as ...? } + const secondAs = this.parseIdentifier(); + if (tokenIsKeywordOrIdentifier(this.state.type)) { + // { type as as something } + hasTypeSpecifier = true; + leftOfAs = firstAs; + rightOfAs = this.parseIdentifier(); + canParseAsKeyword = false; + } else { + // { type as as } + rightOfAs = secondAs; + canParseAsKeyword = false; + } + } else if (tokenIsKeywordOrIdentifier(this.state.type)) { + // { type as something } + canParseAsKeyword = false; + rightOfAs = this.parseIdentifier(); + } else { + // { type as } + hasTypeSpecifier = true; + leftOfAs = firstAs; + } + } else if (tokenIsKeywordOrIdentifier(this.state.type)) { + // { type something ...? } + hasTypeSpecifier = true; + leftOfAs = this.parseIdentifier(); + } + if (hasTypeSpecifier && isInTypeOnlyImportExport) { + this.raise( + pos, + isImport + ? TSErrors.TypeModifierIsUsedInTypeImports + : TSErrors.TypeModifierIsUsedInTypeExports, + ); + } + + node[leftOfAsKey] = leftOfAs; + node[rightOfAsKey] = rightOfAs; + + const kindKey = isImport ? "importKind" : "exportKind"; + node[kindKey] = hasTypeSpecifier ? "type" : "value"; + + if (canParseAsKeyword && this.eatContextual(tt._as)) { + node[rightOfAsKey] = isImport + ? this.parseIdentifier() + : this.parseModuleExportName(); + } + if (!node[rightOfAsKey]) { + node[rightOfAsKey] = cloneIdentifier(node[leftOfAsKey]); + } + if (isImport) { + this.checkLVal(node[rightOfAsKey], "import specifier", BIND_LEXICAL); + } + } }; diff --git a/packages/babel-parser/src/types.js b/packages/babel-parser/src/types.js index e747abc6b5f5..5362caf18d3e 100644 --- a/packages/babel-parser/src/types.js +++ b/packages/babel-parser/src/types.js @@ -903,6 +903,7 @@ export type ImportDeclaration = NodeBase & { export type ImportSpecifier = ModuleSpecifier & { type: "ImportSpecifier", imported: Identifier | StringLiteral, + importKind?: "type" | "value", }; export type ImportDefaultSpecifier = ModuleSpecifier & { @@ -930,6 +931,7 @@ export type ExportSpecifier = NodeBase & { type: "ExportSpecifier", exported: Identifier | StringLiteral, local: Identifier, + exportKind?: "type" | "value", }; export type ExportDefaultSpecifier = NodeBase & { diff --git a/packages/babel-parser/test/fixtures/typescript/export/export-type-from/output.json b/packages/babel-parser/test/fixtures/typescript/export/export-type-from/output.json index e8399c38636e..517cff8768d0 100644 --- a/packages/babel-parser/test/fixtures/typescript/export/export-type-from/output.json +++ b/packages/babel-parser/test/fixtures/typescript/export/export-type-from/output.json @@ -20,6 +20,7 @@ "start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"T"}, "name": "T" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"T"}, diff --git a/packages/babel-parser/test/fixtures/typescript/export/export-type/output.json b/packages/babel-parser/test/fixtures/typescript/export/export-type/output.json index 5c1d6a9647b6..2ab17f0fe674 100644 --- a/packages/babel-parser/test/fixtures/typescript/export/export-type/output.json +++ b/packages/babel-parser/test/fixtures/typescript/export/export-type/output.json @@ -42,6 +42,7 @@ "start":26,"end":27,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":15},"identifierName":"A"}, "name": "A" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":26,"end":27,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":15},"identifierName":"A"}, diff --git a/packages/babel-parser/test/fixtures/typescript/export/internal-comments/output.json b/packages/babel-parser/test/fixtures/typescript/export/internal-comments/output.json index 14f5660ae202..6da84f915b29 100644 --- a/packages/babel-parser/test/fixtures/typescript/export/internal-comments/output.json +++ b/packages/babel-parser/test/fixtures/typescript/export/internal-comments/output.json @@ -20,6 +20,7 @@ "start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28},"identifierName":"A"}, "name": "A" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":27,"end":28,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":28},"identifierName":"A"}, @@ -55,6 +56,7 @@ } ] }, + "exportKind": "value", "exported": { "type": "Identifier", "start":59,"end":60,"loc":{"start":{"line":1,"column":59},"end":{"line":1,"column":60},"identifierName":"C"}, diff --git a/packages/babel-parser/test/fixtures/typescript/import/export-named-import-require/output.json b/packages/babel-parser/test/fixtures/typescript/import/export-named-import-require/output.json index b7915365cced..8c514405ab97 100644 --- a/packages/babel-parser/test/fixtures/typescript/import/export-named-import-require/output.json +++ b/packages/babel-parser/test/fixtures/typescript/import/export-named-import-require/output.json @@ -44,6 +44,7 @@ "start":34,"end":35,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"a"}, "name": "a" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":34,"end":35,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"a"}, diff --git a/packages/babel-parser/test/fixtures/typescript/import/import-default-and-named-id-type/output.json b/packages/babel-parser/test/fixtures/typescript/import/import-default-and-named-id-type/output.json index b91fcd5078b0..753dd0f30f1b 100644 --- a/packages/babel-parser/test/fixtures/typescript/import/import-default-and-named-id-type/output.json +++ b/packages/babel-parser/test/fixtures/typescript/import/import-default-and-named-id-type/output.json @@ -29,6 +29,7 @@ "start":15,"end":18,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":18},"identifierName":"bar"}, "name": "bar" }, + "importKind": "value", "local": { "type": "Identifier", "start":15,"end":18,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":18},"identifierName":"bar"}, diff --git a/packages/babel-parser/test/fixtures/typescript/import/import-named/output.json b/packages/babel-parser/test/fixtures/typescript/import/import-named/output.json index 4f8221972167..ac1e40ac7928 100644 --- a/packages/babel-parser/test/fixtures/typescript/import/import-named/output.json +++ b/packages/babel-parser/test/fixtures/typescript/import/import-named/output.json @@ -20,6 +20,7 @@ "start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"foo"}, "name": "foo" }, + "importKind": "value", "local": { "type": "Identifier", "start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"foo"}, diff --git a/packages/babel-parser/test/fixtures/typescript/import/internal-comments/output.json b/packages/babel-parser/test/fixtures/typescript/import/internal-comments/output.json index 53e1eadab46c..9667fbf9c33f 100644 --- a/packages/babel-parser/test/fixtures/typescript/import/internal-comments/output.json +++ b/packages/babel-parser/test/fixtures/typescript/import/internal-comments/output.json @@ -43,6 +43,7 @@ "start":42,"end":43,"loc":{"start":{"line":1,"column":42},"end":{"line":1,"column":43},"identifierName":"A"}, "name": "A" }, + "importKind": "value", "local": { "type": "Identifier", "start":42,"end":43,"loc":{"start":{"line":1,"column":42},"end":{"line":1,"column":43},"identifierName":"A"}, @@ -78,6 +79,7 @@ } ] }, + "importKind": "value", "local": { "type": "Identifier", "start":74,"end":75,"loc":{"start":{"line":1,"column":74},"end":{"line":1,"column":75},"identifierName":"C"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-after/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-after/output.json index f867f1ebfbc2..382d4fcac08b 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-after/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-after/output.json @@ -41,6 +41,7 @@ "start":40,"end":43,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":12},"identifierName":"foo"}, "name": "foo" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":40,"end":43,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":12},"identifierName":"foo"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-before/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-before/output.json index e9ad92c6829b..0058fdfd1c63 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-before/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-declare-function-before/output.json @@ -20,6 +20,7 @@ "start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"foo"}, "name": "foo" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":9,"end":12,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":12},"identifierName":"foo"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-enum-after/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-enum-after/output.json index 46d31f603be2..69654c84b6ec 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-enum-after/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-enum-after/output.json @@ -37,6 +37,7 @@ "start":70,"end":74,"loc":{"start":{"line":5,"column":9},"end":{"line":5,"column":13},"identifierName":"Test"}, "name": "Test" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":78,"end":85,"loc":{"start":{"line":5,"column":17},"end":{"line":5,"column":24},"identifierName":"default"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-enum-before/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-enum-before/output.json index 1ee9c0bf6b56..66814a6eb848 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-enum-before/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-enum-before/output.json @@ -20,6 +20,7 @@ "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"Test"}, "name": "Test" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":17,"end":24,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":24},"identifierName":"default"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-interface-after/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-interface-after/output.json index b24638468861..13baab57ae9f 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-interface-after/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-interface-after/output.json @@ -34,6 +34,7 @@ "start":24,"end":25,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"A"}, "name": "A" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":24,"end":25,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"A"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-interface-before/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-interface-before/output.json index 1d0567998efb..091f98022cb1 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-interface-before/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-interface-before/output.json @@ -20,6 +20,7 @@ "start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"A"}, "name": "A" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"A"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-namespace/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-namespace/output.json index 80c8faf0bbb8..0e29a80b2993 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-namespace/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-namespace/output.json @@ -34,6 +34,7 @@ "start":25,"end":26,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":10},"identifierName":"N"}, "name": "N" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":25,"end":26,"loc":{"start":{"line":3,"column":9},"end":{"line":3,"column":10},"identifierName":"N"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-type-after/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-type-after/output.json index b5f2fb8ebd93..d4e0ffde50d6 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-type-after/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-type-after/output.json @@ -33,6 +33,7 @@ "start":26,"end":27,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"A"}, "name": "A" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":26,"end":27,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":10},"identifierName":"A"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/export-type-before/output.json b/packages/babel-parser/test/fixtures/typescript/scope/export-type-before/output.json index 3da921f98898..90abe10759e4 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/export-type-before/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/export-type-before/output.json @@ -20,6 +20,7 @@ "start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"A"}, "name": "A" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":9,"end":10,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":10},"identifierName":"A"}, diff --git a/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration/output.json b/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration/output.json index 54e57b9a6d14..0d4eb7d84b85 100644 --- a/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration/output.json +++ b/packages/babel-parser/test/fixtures/typescript/scope/function-type-before-declaration/output.json @@ -58,6 +58,7 @@ "start":46,"end":47,"loc":{"start":{"line":4,"column":9},"end":{"line":4,"column":10},"identifierName":"f"}, "name": "f" }, + "exportKind": "value", "exported": { "type": "Identifier", "start":46,"end":47,"loc":{"start":{"line":4,"column":9},"end":{"line":4,"column":10},"identifierName":"f"}, diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-basic/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-basic/input.ts new file mode 100644 index 000000000000..1b15744ea1ca --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-basic/input.ts @@ -0,0 +1 @@ +export { type A, type B, type C } from "foo"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-basic/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-basic/output.json new file mode 100644 index 000000000000..4c88696f67c6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-basic/output.json @@ -0,0 +1,75 @@ +{ + "type": "File", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":45}}, + "program": { + "type": "Program", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":45}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":45}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":9,"end":15,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":15}}, + "local": { + "type": "Identifier", + "start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"A"}, + "name": "A" + }, + "exportKind": "type", + "exported": { + "type": "Identifier", + "start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"A"}, + "name": "A" + } + }, + { + "type": "ExportSpecifier", + "start":17,"end":23,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":23}}, + "local": { + "type": "Identifier", + "start":22,"end":23,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":23},"identifierName":"B"}, + "name": "B" + }, + "exportKind": "type", + "exported": { + "type": "Identifier", + "start":22,"end":23,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":23},"identifierName":"B"}, + "name": "B" + } + }, + { + "type": "ExportSpecifier", + "start":25,"end":31,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":31}}, + "local": { + "type": "Identifier", + "start":30,"end":31,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":31},"identifierName":"C"}, + "name": "C" + }, + "exportKind": "type", + "exported": { + "type": "Identifier", + "start":30,"end":31,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":31},"identifierName":"C"}, + "name": "C" + } + } + ], + "source": { + "type": "StringLiteral", + "start":39,"end":44,"loc":{"start":{"line":1,"column":39},"end":{"line":1,"column":44}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + }, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-invalid-type-in-type/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-invalid-type-in-type/input.ts new file mode 100644 index 000000000000..31c6395162cb --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-invalid-type-in-type/input.ts @@ -0,0 +1 @@ +export type { type foo } from "foo"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-invalid-type-in-type/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-invalid-type-in-type/output.json new file mode 100644 index 000000000000..ad97aea5407b --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-invalid-type-in-type/output.json @@ -0,0 +1,48 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "errors": [ + "SyntaxError: The 'type' modifier cannot be used on a named export when 'export type' is used on its export statement. (1:14)" + ], + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "exportKind": "type", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":14,"end":22,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":22}}, + "local": { + "type": "Identifier", + "start":19,"end":22,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":22},"identifierName":"foo"}, + "name": "foo" + }, + "exported": { + "type": "Identifier", + "start":19,"end":22,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":22},"identifierName":"foo"}, + "name": "foo" + }, + "exportKind": "type" + } + ], + "source": { + "type": "StringLiteral", + "start":30,"end":35,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":35}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + }, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-and-named-type/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-and-named-type/input.ts new file mode 100644 index 000000000000..704b11597e95 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-and-named-type/input.ts @@ -0,0 +1 @@ +export { Component, type ComponentProps } from "./exports.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-and-named-type/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-and-named-type/output.json new file mode 100644 index 000000000000..7488dd1ac788 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-and-named-type/output.json @@ -0,0 +1,60 @@ +{ + "type": "File", + "start":0,"end":62,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}}, + "program": { + "type": "Program", + "start":0,"end":62,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":62,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18}}, + "local": { + "type": "Identifier", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18},"identifierName":"Component"}, + "name": "Component" + }, + "exported": { + "type": "Identifier", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18},"identifierName":"Component"}, + "name": "Component" + }, + "exportKind": "value" + }, + { + "type": "ExportSpecifier", + "start":20,"end":39,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":39}}, + "local": { + "type": "Identifier", + "start":25,"end":39,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":39},"identifierName":"ComponentProps"}, + "name": "ComponentProps" + }, + "exported": { + "type": "Identifier", + "start":25,"end":39,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":39},"identifierName":"ComponentProps"}, + "name": "ComponentProps" + }, + "exportKind": "type" + } + ], + "source": { + "type": "StringLiteral", + "start":47,"end":61,"loc":{"start":{"line":1,"column":47},"end":{"line":1,"column":61}}, + "extra": { + "rawValue": "./exports.js", + "raw": "\"./exports.js\"" + }, + "value": "./exports.js" + }, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-as/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-as/input.ts new file mode 100644 index 000000000000..37f938f792d0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-as/input.ts @@ -0,0 +1 @@ +export { type as as } from "./mod.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-as/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-as/output.json new file mode 100644 index 000000000000..22c7de50fd03 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-as/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":38}}, + "program": { + "type": "Program", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":38}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":38}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":9,"end":19,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":19}}, + "local": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"type"}, + "name": "type" + }, + "exported": { + "type": "Identifier", + "start":17,"end":19,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":19},"identifierName":"as"}, + "name": "as" + }, + "exportKind": "value" + } + ], + "source": { + "type": "StringLiteral", + "start":27,"end":37,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":37}}, + "extra": { + "rawValue": "./mod.js", + "raw": "\"./mod.js\"" + }, + "value": "./mod.js" + }, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-keyword/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-keyword/input.ts new file mode 100644 index 000000000000..ca6b2b9131a2 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-keyword/input.ts @@ -0,0 +1,2 @@ +const type = {}; +export { type as if }; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-keyword/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-keyword/output.json new file mode 100644 index 000000000000..0e29350fb3d6 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type-as-keyword/output.json @@ -0,0 +1,58 @@ +{ + "type": "File", + "start":0,"end":39,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":22}}, + "program": { + "type": "Program", + "start":0,"end":39,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":22}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":16,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":16}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":15,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":15}}, + "id": { + "type": "Identifier", + "start":6,"end":10,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":10},"identifierName":"type"}, + "name": "type" + }, + "init": { + "type": "ObjectExpression", + "start":13,"end":15,"loc":{"start":{"line":1,"column":13},"end":{"line":1,"column":15}}, + "properties": [] + } + } + ], + "kind": "const" + }, + { + "type": "ExportNamedDeclaration", + "start":17,"end":39,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":22}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":26,"end":36,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":19}}, + "local": { + "type": "Identifier", + "start":26,"end":30,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":13},"identifierName":"type"}, + "name": "type" + }, + "exported": { + "type": "Identifier", + "start":34,"end":36,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":19},"identifierName":"if"}, + "name": "if" + }, + "exportKind": "value" + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type/input.ts new file mode 100644 index 000000000000..4c458f9f5763 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type/input.ts @@ -0,0 +1 @@ +export { type } from "./mod.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type/output.json new file mode 100644 index 000000000000..fa9cde2a7750 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-named-type/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}}, + "program": { + "type": "Program", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13}}, + "local": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"type"}, + "name": "type" + }, + "exportKind": "value", + "exported": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"type"}, + "name": "type" + } + } + ], + "source": { + "type": "StringLiteral", + "start":21,"end":31,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":31}}, + "extra": { + "rawValue": "./mod.js", + "raw": "\"./mod.js\"" + }, + "value": "./mod.js" + }, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-as-as-keyword/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-as-as-keyword/input.ts new file mode 100644 index 000000000000..7c9932a83a46 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-as-as-keyword/input.ts @@ -0,0 +1,2 @@ +const as = {}; +export { type as as if }; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-as-as-keyword/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-as-as-keyword/output.json new file mode 100644 index 000000000000..f9271906199e --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-as-as-keyword/output.json @@ -0,0 +1,58 @@ +{ + "type": "File", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":25}}, + "program": { + "type": "Program", + "start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":25}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":13,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":13}}, + "id": { + "type": "Identifier", + "start":6,"end":8,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":8},"identifierName":"as"}, + "name": "as" + }, + "init": { + "type": "ObjectExpression", + "start":11,"end":13,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":13}}, + "properties": [] + } + } + ], + "kind": "const" + }, + { + "type": "ExportNamedDeclaration", + "start":15,"end":40,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":25}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":24,"end":37,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":22}}, + "local": { + "type": "Identifier", + "start":29,"end":31,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":16},"identifierName":"as"}, + "name": "as" + }, + "exported": { + "type": "Identifier", + "start":35,"end":37,"loc":{"start":{"line":2,"column":20},"end":{"line":2,"column":22},"identifierName":"if"}, + "name": "if" + }, + "exportKind": "type" + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-keyword/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-keyword/input.ts new file mode 100644 index 000000000000..caba0b5d2314 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-keyword/input.ts @@ -0,0 +1,2 @@ +const if = {}; +export { type if }; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-keyword/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-keyword/output.json new file mode 100644 index 000000000000..510f321617d5 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-keyword/output.json @@ -0,0 +1,58 @@ +{ + "type": "File", + "start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":19}}, + "program": { + "type": "Program", + "start":0,"end":34,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":19}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "VariableDeclaration", + "start":0,"end":14,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":14}}, + "declarations": [ + { + "type": "VariableDeclarator", + "start":6,"end":13,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":13}}, + "id": { + "type": "Identifier", + "start":6,"end":8,"loc":{"start":{"line":1,"column":6},"end":{"line":1,"column":8},"identifierName":"if"}, + "name": "if" + }, + "init": { + "type": "ObjectExpression", + "start":11,"end":13,"loc":{"start":{"line":1,"column":11},"end":{"line":1,"column":13}}, + "properties": [] + } + } + ], + "kind": "const" + }, + { + "type": "ExportNamedDeclaration", + "start":15,"end":34,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":19}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":24,"end":31,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":16}}, + "local": { + "type": "Identifier", + "start":29,"end":31,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":16},"identifierName":"if"}, + "name": "if" + }, + "exported": { + "type": "Identifier", + "start":29,"end":31,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":16},"identifierName":"if"}, + "name": "if" + }, + "exportKind": "type" + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-named-as/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-named-as/input.ts new file mode 100644 index 000000000000..b3bbea7354c1 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-named-as/input.ts @@ -0,0 +1 @@ +export { type as } from "./mod.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-named-as/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-named-as/output.json new file mode 100644 index 000000000000..e2ca3b3f46df --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/export-type-only-named-as/output.json @@ -0,0 +1,45 @@ +{ + "type": "File", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}}, + "program": { + "type": "Program", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ExportNamedDeclaration", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":9,"end":16,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":16}}, + "local": { + "type": "Identifier", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":16},"identifierName":"as"}, + "name": "as" + }, + "exportKind": "type", + "exported": { + "type": "Identifier", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":16},"identifierName":"as"}, + "name": "as" + } + } + ], + "source": { + "type": "StringLiteral", + "start":24,"end":34,"loc":{"start":{"line":1,"column":24},"end":{"line":1,"column":34}}, + "extra": { + "rawValue": "./mod.js", + "raw": "\"./mod.js\"" + }, + "value": "./mod.js" + }, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/expport-invalid-escaped-type-only/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/expport-invalid-escaped-type-only/input.ts new file mode 100644 index 000000000000..3e7cfa0ce5e4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/expport-invalid-escaped-type-only/input.ts @@ -0,0 +1 @@ +export { typ\u0065 as } from "x"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/expport-invalid-escaped-type-only/options.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/expport-invalid-escaped-type-only/options.json new file mode 100644 index 000000000000..2a7af925f7ae --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/expport-invalid-escaped-type-only/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "Unexpected token (1:22)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-basic/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-basic/input.ts new file mode 100644 index 000000000000..97eff0907bee --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-basic/input.ts @@ -0,0 +1 @@ +import { type A, type B, type C } from "foo"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-basic/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-basic/output.json new file mode 100644 index 000000000000..7799fb70dc3d --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-basic/output.json @@ -0,0 +1,74 @@ +{ + "type": "File", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":45}}, + "program": { + "type": "Program", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":45}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":45,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":45}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":15,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":15}}, + "imported": { + "type": "Identifier", + "start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"A"}, + "name": "A" + }, + "importKind": "type", + "local": { + "type": "Identifier", + "start":14,"end":15,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":15},"identifierName":"A"}, + "name": "A" + } + }, + { + "type": "ImportSpecifier", + "start":17,"end":23,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":23}}, + "imported": { + "type": "Identifier", + "start":22,"end":23,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":23},"identifierName":"B"}, + "name": "B" + }, + "importKind": "type", + "local": { + "type": "Identifier", + "start":22,"end":23,"loc":{"start":{"line":1,"column":22},"end":{"line":1,"column":23},"identifierName":"B"}, + "name": "B" + } + }, + { + "type": "ImportSpecifier", + "start":25,"end":31,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":31}}, + "imported": { + "type": "Identifier", + "start":30,"end":31,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":31},"identifierName":"C"}, + "name": "C" + }, + "importKind": "type", + "local": { + "type": "Identifier", + "start":30,"end":31,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":31},"identifierName":"C"}, + "name": "C" + } + } + ], + "source": { + "type": "StringLiteral", + "start":39,"end":44,"loc":{"start":{"line":1,"column":39},"end":{"line":1,"column":44}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-escaped-type-only/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-escaped-type-only/input.ts new file mode 100644 index 000000000000..313c9cfc2370 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-escaped-type-only/input.ts @@ -0,0 +1 @@ +import { typ\u0065 as } from "x"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-escaped-type-only/options.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-escaped-type-only/options.json new file mode 100644 index 000000000000..2a7af925f7ae --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-escaped-type-only/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "Unexpected token (1:22)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-named-type-as-keyword/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-named-type-as-keyword/input.ts new file mode 100644 index 000000000000..061fadb8439d --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-named-type-as-keyword/input.ts @@ -0,0 +1 @@ +import { type as if } from "mod"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-named-type-as-keyword/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-named-type-as-keyword/output.json new file mode 100644 index 000000000000..7a37d3e1e7af --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-named-type-as-keyword/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":33}}, + "program": { + "type": "Program", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":33}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":33,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":33}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":19,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":19}}, + "imported": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"type"}, + "name": "type" + }, + "local": { + "type": "Identifier", + "start":17,"end":19,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":19},"identifierName":"if"}, + "name": "if" + }, + "importKind": "value" + } + ], + "source": { + "type": "StringLiteral", + "start":27,"end":32,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":32}}, + "extra": { + "rawValue": "mod", + "raw": "\"mod\"" + }, + "value": "mod" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-in-type/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-in-type/input.ts new file mode 100644 index 000000000000..b15216bc9806 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-in-type/input.ts @@ -0,0 +1 @@ +import type { type foo } from "foo"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-in-type/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-in-type/output.json new file mode 100644 index 000000000000..65c51671af8b --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-in-type/output.json @@ -0,0 +1,47 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "errors": [ + "SyntaxError: The 'type' modifier cannot be used on a named import when 'import type' is used on its import statement. (1:14)" + ], + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "importKind": "type", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":14,"end":22,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":22}}, + "imported": { + "type": "Identifier", + "start":19,"end":22,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":22},"identifierName":"foo"}, + "name": "foo" + }, + "local": { + "type": "Identifier", + "start":19,"end":22,"loc":{"start":{"line":1,"column":19},"end":{"line":1,"column":22},"identifierName":"foo"}, + "name": "foo" + }, + "importKind": "type" + } + ], + "source": { + "type": "StringLiteral", + "start":30,"end":35,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":35}}, + "extra": { + "rawValue": "foo", + "raw": "\"foo\"" + }, + "value": "foo" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-as-keyword/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-as-keyword/input.ts new file mode 100644 index 000000000000..3ef90464a510 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-as-keyword/input.ts @@ -0,0 +1 @@ +import { type as as if } from "mod"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-as-keyword/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-as-keyword/output.json new file mode 100644 index 000000000000..8b80e58814ff --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-as-keyword/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "program": { + "type": "Program", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":36,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":36}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":22,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":22}}, + "imported": { + "type": "Identifier", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":16},"identifierName":"as"}, + "name": "as" + }, + "local": { + "type": "Identifier", + "start":20,"end":22,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":22},"identifierName":"if"}, + "name": "if" + }, + "importKind": "type" + } + ], + "source": { + "type": "StringLiteral", + "start":30,"end":35,"loc":{"start":{"line":1,"column":30},"end":{"line":1,"column":35}}, + "extra": { + "rawValue": "mod", + "raw": "\"mod\"" + }, + "value": "mod" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-string/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-string/input.ts new file mode 100644 index 000000000000..05b291a2093a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-string/input.ts @@ -0,0 +1 @@ +import { type foo as "bar" } from "mod"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-string/options.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-string/options.json new file mode 100644 index 000000000000..786efcf1eab4 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-invalid-type-only-as-string/options.json @@ -0,0 +1,7 @@ +{ + "sourceType": "module", + "plugins": [ + "typescript" + ], + "throws": "Unexpected token (1:21)" +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-and-named-type/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-and-named-type/input.ts new file mode 100644 index 000000000000..52e743608261 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-and-named-type/input.ts @@ -0,0 +1 @@ +import { Component, type ComponentProps } from "./exports.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-and-named-type/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-and-named-type/output.json new file mode 100644 index 000000000000..ee7a3a58078a --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-and-named-type/output.json @@ -0,0 +1,59 @@ +{ + "type": "File", + "start":0,"end":62,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}}, + "program": { + "type": "Program", + "start":0,"end":62,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":62,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":62}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18}}, + "imported": { + "type": "Identifier", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18},"identifierName":"Component"}, + "name": "Component" + }, + "local": { + "type": "Identifier", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18},"identifierName":"Component"}, + "name": "Component" + }, + "importKind": "value" + }, + { + "type": "ImportSpecifier", + "start":20,"end":39,"loc":{"start":{"line":1,"column":20},"end":{"line":1,"column":39}}, + "imported": { + "type": "Identifier", + "start":25,"end":39,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":39},"identifierName":"ComponentProps"}, + "name": "ComponentProps" + }, + "local": { + "type": "Identifier", + "start":25,"end":39,"loc":{"start":{"line":1,"column":25},"end":{"line":1,"column":39},"identifierName":"ComponentProps"}, + "name": "ComponentProps" + }, + "importKind": "type" + } + ], + "source": { + "type": "StringLiteral", + "start":47,"end":61,"loc":{"start":{"line":1,"column":47},"end":{"line":1,"column":61}}, + "extra": { + "rawValue": "./exports.js", + "raw": "\"./exports.js\"" + }, + "value": "./exports.js" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type-as-as/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type-as-as/input.ts new file mode 100644 index 000000000000..bc2ee3b22029 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type-as-as/input.ts @@ -0,0 +1 @@ +import { type as as } from "./mod.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type-as-as/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type-as-as/output.json new file mode 100644 index 000000000000..16645aae9765 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type-as-as/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":38}}, + "program": { + "type": "Program", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":38}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":38,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":38}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":19,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":19}}, + "imported": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"type"}, + "name": "type" + }, + "local": { + "type": "Identifier", + "start":17,"end":19,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":19},"identifierName":"as"}, + "name": "as" + }, + "importKind": "value" + } + ], + "source": { + "type": "StringLiteral", + "start":27,"end":37,"loc":{"start":{"line":1,"column":27},"end":{"line":1,"column":37}}, + "extra": { + "rawValue": "./mod.js", + "raw": "\"./mod.js\"" + }, + "value": "./mod.js" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type/input.ts new file mode 100644 index 000000000000..33f4c30dd0dd --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type/input.ts @@ -0,0 +1 @@ +import { type } from "./mod.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type/output.json new file mode 100644 index 000000000000..341d6b506293 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-named-type/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}}, + "program": { + "type": "Program", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13}}, + "imported": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"type"}, + "name": "type" + }, + "importKind": "value", + "local": { + "type": "Identifier", + "start":9,"end":13,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":13},"identifierName":"type"}, + "name": "type" + } + } + ], + "source": { + "type": "StringLiteral", + "start":21,"end":31,"loc":{"start":{"line":1,"column":21},"end":{"line":1,"column":31}}, + "extra": { + "rawValue": "./mod.js", + "raw": "\"./mod.js\"" + }, + "value": "./mod.js" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-and-export/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-and-export/input.ts new file mode 100644 index 000000000000..0b84733b65e0 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-and-export/input.ts @@ -0,0 +1,2 @@ +import { type Foo1 } from "mod"; +export { Foo1 }; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-and-export/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-and-export/output.json new file mode 100644 index 000000000000..ff0c51d3b3ef --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-and-export/output.json @@ -0,0 +1,68 @@ +{ + "type": "File", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":16}}, + "program": { + "type": "Program", + "start":0,"end":49,"loc":{"start":{"line":1,"column":0},"end":{"line":2,"column":16}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":32,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":32}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":18,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":18}}, + "imported": { + "type": "Identifier", + "start":14,"end":18,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":18},"identifierName":"Foo1"}, + "name": "Foo1" + }, + "local": { + "type": "Identifier", + "start":14,"end":18,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":18},"identifierName":"Foo1"}, + "name": "Foo1" + }, + "importKind": "type" + } + ], + "source": { + "type": "StringLiteral", + "start":26,"end":31,"loc":{"start":{"line":1,"column":26},"end":{"line":1,"column":31}}, + "extra": { + "rawValue": "mod", + "raw": "\"mod\"" + }, + "value": "mod" + } + }, + { + "type": "ExportNamedDeclaration", + "start":33,"end":49,"loc":{"start":{"line":2,"column":0},"end":{"line":2,"column":16}}, + "exportKind": "value", + "specifiers": [ + { + "type": "ExportSpecifier", + "start":42,"end":46,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":13}}, + "local": { + "type": "Identifier", + "start":42,"end":46,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":13},"identifierName":"Foo1"}, + "name": "Foo1" + }, + "exportKind": "value", + "exported": { + "type": "Identifier", + "start":42,"end":46,"loc":{"start":{"line":2,"column":9},"end":{"line":2,"column":13},"identifierName":"Foo1"}, + "name": "Foo1" + } + } + ], + "source": null, + "declaration": null + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-named-as/input.ts b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-named-as/input.ts new file mode 100644 index 000000000000..e6fbba5e5919 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-named-as/input.ts @@ -0,0 +1 @@ +import { type as } from "./mod.js"; diff --git a/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-named-as/output.json b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-named-as/output.json new file mode 100644 index 000000000000..92edacf58ae8 --- /dev/null +++ b/packages/babel-parser/test/fixtures/typescript/type-only-import-export-specifiers/import-type-only-named-as/output.json @@ -0,0 +1,44 @@ +{ + "type": "File", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}}, + "program": { + "type": "Program", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}}, + "sourceType": "module", + "interpreter": null, + "body": [ + { + "type": "ImportDeclaration", + "start":0,"end":35,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":35}}, + "importKind": "value", + "specifiers": [ + { + "type": "ImportSpecifier", + "start":9,"end":16,"loc":{"start":{"line":1,"column":9},"end":{"line":1,"column":16}}, + "imported": { + "type": "Identifier", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":16},"identifierName":"as"}, + "name": "as" + }, + "importKind": "type", + "local": { + "type": "Identifier", + "start":14,"end":16,"loc":{"start":{"line":1,"column":14},"end":{"line":1,"column":16},"identifierName":"as"}, + "name": "as" + } + } + ], + "source": { + "type": "StringLiteral", + "start":24,"end":34,"loc":{"start":{"line":1,"column":24},"end":{"line":1,"column":34}}, + "extra": { + "rawValue": "./mod.js", + "raw": "\"./mod.js\"" + }, + "value": "./mod.js" + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration-error/output.json b/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration-error/output.json index 3df1338cbc58..5e09de512341 100644 --- a/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration-error/output.json +++ b/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration-error/output.json @@ -32,6 +32,7 @@ "start":26,"end":29,"loc":{"start":{"line":1,"column":26},"end":{"line":1,"column":29},"identifierName":"Bar"}, "name": "Bar" }, + "importKind": "value", "local": { "type": "Identifier", "start":26,"end":29,"loc":{"start":{"line":1,"column":26},"end":{"line":1,"column":29},"identifierName":"Bar"}, @@ -46,6 +47,7 @@ "start":31,"end":34,"loc":{"start":{"line":1,"column":31},"end":{"line":1,"column":34},"identifierName":"Baz"}, "name": "Baz" }, + "importKind": "value", "local": { "type": "Identifier", "start":31,"end":34,"loc":{"start":{"line":1,"column":31},"end":{"line":1,"column":34},"identifierName":"Baz"}, diff --git a/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration/output.json b/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration/output.json index b0f9cac40033..62b9afdd1083 100644 --- a/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration/output.json +++ b/packages/babel-parser/test/fixtures/typescript/types/import-type-declaration/output.json @@ -45,6 +45,7 @@ "start":42,"end":43,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":15},"identifierName":"A"}, "name": "A" }, + "importKind": "value", "local": { "type": "Identifier", "start":42,"end":43,"loc":{"start":{"line":2,"column":14},"end":{"line":2,"column":15},"identifierName":"A"}, @@ -59,6 +60,7 @@ "start":45,"end":46,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":18},"identifierName":"B"}, "name": "B" }, + "importKind": "value", "local": { "type": "Identifier", "start":45,"end":46,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":18},"identifierName":"B"}, diff --git a/packages/babel-plugin-transform-typescript/src/index.ts b/packages/babel-plugin-transform-typescript/src/index.ts index 8bad5c22cf23..2975ae471c3c 100644 --- a/packages/babel-plugin-transform-typescript/src/index.ts +++ b/packages/babel-plugin-transform-typescript/src/index.ts @@ -265,6 +265,25 @@ export default declare((api: ConfigAPI, opts: Options): Plugin => { continue; } + const importsToRemove: Set> = new Set(); + const specifiersLength = stmt.node.specifiers.length; + const isAllSpecifiersElided = () => + specifiersLength > 0 && + specifiersLength === importsToRemove.size; + + for (const specifier of stmt.node.specifiers) { + if ( + specifier.type === "ImportSpecifier" && + specifier.importKind === "type" + ) { + registerGlobalType(programNode, specifier.local.name); + const binding = stmt.scope.getBinding(specifier.local.name); + if (binding) { + importsToRemove.add(binding.path); + } + } + } + // If onlyRemoveTypeImports is `true`, only remove type-only imports // and exports introduced in TypeScript 3.8. if (onlyRemoveTypeImports) { @@ -277,9 +296,6 @@ export default declare((api: ConfigAPI, opts: Options): Plugin => { continue; } - let allElided = true; - const importsToRemove: NodePath[] = []; - for (const specifier of stmt.node.specifiers) { const binding = stmt.scope.getBinding(specifier.local.name); @@ -289,28 +305,29 @@ export default declare((api: ConfigAPI, opts: Options): Plugin => { // just bail if there is no binding, since chances are good that if // the import statement was injected then it wasn't a typescript type // import anyway. - if ( - binding && - isImportTypeOnly({ - binding, - programPath: path, - pragmaImportName, - pragmaFragImportName, - }) - ) { - importsToRemove.push(binding.path); - } else { - allElided = false; - NEEDS_EXPLICIT_ESM.set(path.node, false); + if (!importsToRemove.has(binding.path)) { + if ( + binding && + isImportTypeOnly({ + binding, + programPath: path, + pragmaImportName, + pragmaFragImportName, + }) + ) { + importsToRemove.add(binding.path); + } else { + NEEDS_EXPLICIT_ESM.set(path.node, false); + } } } + } - if (allElided) { - stmt.remove(); - } else { - for (const importPath of importsToRemove) { - importPath.remove(); - } + if (isAllSpecifiersElided()) { + stmt.remove(); + } else { + for (const importPath of importsToRemove) { + importPath.remove(); } } @@ -365,6 +382,21 @@ export default declare((api: ConfigAPI, opts: Options): Plugin => { return; } + // remove export declaration that is filled with type-only specifiers + // export { type A1, type A2 } from "a"; + if ( + path.node.source && + path.node.specifiers.length > 0 && + path.node.specifiers.every( + specifier => + specifier.type === "ExportSpecifier" && + specifier.exportKind === "type", + ) + ) { + path.remove(); + return; + } + // remove export declaration if it's exporting only types // This logic is needed when exportKind is "value", because // currently the "type" keyword is optional. @@ -392,7 +424,10 @@ export default declare((api: ConfigAPI, opts: Options): Plugin => { // remove type exports type Parent = t.ExportDeclaration & { source?: t.StringLiteral }; const parent = path.parent as Parent; - if (!parent.source && isGlobalType(path, path.node.local.name)) { + if ( + (!parent.source && isGlobalType(path, path.node.local.name)) || + path.node.exportKind === "type" + ) { path.remove(); } }, diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/input.ts new file mode 100644 index 000000000000..d268127794d9 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/input.ts @@ -0,0 +1,2 @@ +class Foo {} +export { type Foo }; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/output.mjs new file mode 100644 index 000000000000..736b92725dc2 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-1/output.mjs @@ -0,0 +1,3 @@ +class Foo {} + +export {}; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/input.ts new file mode 100644 index 000000000000..b7724a25247d --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/input.ts @@ -0,0 +1 @@ +export { type A1, type A2 } from "a" diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/output.mjs new file mode 100644 index 000000000000..cb0ff5c3b541 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-2/output.mjs @@ -0,0 +1 @@ +export {}; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/input.ts new file mode 100644 index 000000000000..a6431530d3ac --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/input.ts @@ -0,0 +1 @@ +export { type A1, type A2, A3 } from "a" diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/output.mjs new file mode 100644 index 000000000000..da23041dfb5d --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/exports/type-only-export-specifier-3/output.mjs @@ -0,0 +1 @@ +export { A3 } from "a"; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts index 744ae808eaa9..6b2b75d9f454 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/input.ts @@ -10,4 +10,6 @@ import "g"; import type H from "h"; import type { I, I2 } from "i"; import type * as J from "j"; +import { type K1, type K2 } from "k"; +import { type L1, L2, type L3 } from "l"; ; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs index d86475cacac8..78a426b356b2 100644 --- a/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/only-remove-type-imports/output.mjs @@ -5,4 +5,5 @@ import d, { d2 } from "d"; import e, { e3 as e4 } from "e"; import "f"; import "g"; +import { L2 } from "l"; ; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/input.ts new file mode 100644 index 000000000000..e4fde7f90cb3 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/input.ts @@ -0,0 +1,2 @@ +import { Foo1, type Foo2 } from "Foo"; +Foo1; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/output.mjs new file mode 100644 index 000000000000..b960b41f8c81 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-1/output.mjs @@ -0,0 +1,2 @@ +import { Foo1 } from "Foo"; +Foo1; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/input.ts new file mode 100644 index 000000000000..d40d26bca8f4 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/input.ts @@ -0,0 +1 @@ +import { type Foo1, type Foo2 } from "Foo"; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/output.mjs new file mode 100644 index 000000000000..cb0ff5c3b541 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-2/output.mjs @@ -0,0 +1 @@ +export {}; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-3/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-3/input.ts new file mode 100644 index 000000000000..d98c1b3715be --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-3/input.ts @@ -0,0 +1,2 @@ +import { type Foo1, type Foo2 } from "Foo"; +export { Foo1, Foo2 }; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-3/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-3/output.mjs new file mode 100644 index 000000000000..cb0ff5c3b541 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-3/output.mjs @@ -0,0 +1 @@ +export {}; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/input.ts b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/input.ts new file mode 100644 index 000000000000..c8a5c01958be --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/input.ts @@ -0,0 +1 @@ +import { type A } from "x"; diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/options.json b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/options.json new file mode 100644 index 000000000000..0ec61d2b5e55 --- /dev/null +++ b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/options.json @@ -0,0 +1,10 @@ +{ + "plugins": [ + [ + "transform-typescript", + { + "onlyRemoveTypeImports": true + } + ] + ] +} diff --git a/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/output.mjs b/packages/babel-plugin-transform-typescript/test/fixtures/imports/type-only-import-specifier-4/output.mjs new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/babel-types/src/ast-types/generated/index.ts b/packages/babel-types/src/ast-types/generated/index.ts index 8a8658e8d357..395812181aa3 100644 --- a/packages/babel-types/src/ast-types/generated/index.ts +++ b/packages/babel-types/src/ast-types/generated/index.ts @@ -812,6 +812,7 @@ export interface ExportSpecifier extends BaseNode { type: "ExportSpecifier"; local: Identifier; exported: Identifier | StringLiteral; + exportKind?: "type" | "value" | null; } export interface ForOfStatement extends BaseNode { @@ -846,7 +847,7 @@ export interface ImportSpecifier extends BaseNode { type: "ImportSpecifier"; local: Identifier; imported: Identifier | StringLiteral; - importKind?: "type" | "typeof" | null; + importKind?: "type" | "typeof" | "value" | null; } export interface MetaProperty extends BaseNode { diff --git a/packages/babel-types/src/definitions/core.ts b/packages/babel-types/src/definitions/core.ts index a0921f49c864..f03ebc9b218a 100644 --- a/packages/babel-types/src/definitions/core.ts +++ b/packages/babel-types/src/definitions/core.ts @@ -1549,6 +1549,11 @@ defineType("ExportSpecifier", { exported: { validate: assertNodeType("Identifier", "StringLiteral"), }, + exportKind: { + // And TypeScript's "export { type foo } from" + validate: assertOneOf("type", "value"), + optional: true, + }, }, }); @@ -1666,7 +1671,8 @@ defineType("ImportSpecifier", { }, importKind: { // Handle Flowtype's extension "import {typeof foo} from" - validate: assertOneOf("type", "typeof"), + // And TypeScript's "import { type foo } from" + validate: assertOneOf("type", "typeof", "value"), optional: true, }, },