Skip to content

Commit ed97dee

Browse files
committed
ignore invalid ts export type * from x (#2329)
1 parent 0905d85 commit ed97dee

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

internal/js_parser/ts_parser.go

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -988,16 +988,44 @@ func (p *parser) skipTypeScriptInterfaceStmt(opts parseStmtOpts) {
988988
}
989989

990990
func (p *parser) skipTypeScriptTypeStmt(opts parseStmtOpts) {
991-
if opts.isExport && p.lexer.Token == js_lexer.TOpenBrace {
992-
// "export type {foo}"
993-
// "export type {foo} from 'bar'"
994-
p.parseExportClause()
995-
if p.lexer.IsContextualKeyword("from") {
991+
if opts.isExport {
992+
switch p.lexer.Token {
993+
case js_lexer.TOpenBrace:
994+
// "export type {foo}"
995+
// "export type {foo} from 'bar'"
996+
p.parseExportClause()
997+
if p.lexer.IsContextualKeyword("from") {
998+
p.lexer.Next()
999+
p.parsePath()
1000+
}
1001+
p.lexer.ExpectOrInsertSemicolon()
1002+
return
1003+
1004+
// This is invalid TypeScript, and is rejected by the TypeScript compiler:
1005+
//
1006+
// example.ts:1:1 - error TS1383: Only named exports may use 'export type'.
1007+
//
1008+
// 1 export type * from './types'
1009+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1010+
//
1011+
// However, people may not know this and then blame esbuild for it not
1012+
// working. So we parse it anyway and then discard it (since we always
1013+
// discard all types). People who do this should be running the TypeScript
1014+
// type checker when using TypeScript, which will then report this error.
1015+
case js_lexer.TAsterisk:
1016+
// "export type * from 'path'"
9961017
p.lexer.Next()
1018+
if p.lexer.IsContextualKeyword("as") {
1019+
// "export type * as ns from 'path'"
1020+
p.lexer.Next()
1021+
p.parseClauseAlias("export")
1022+
p.lexer.Next()
1023+
}
1024+
p.lexer.ExpectContextualKeyword("from")
9971025
p.parsePath()
1026+
p.lexer.ExpectOrInsertSemicolon()
1027+
return
9981028
}
999-
p.lexer.ExpectOrInsertSemicolon()
1000-
return
10011029
}
10021030

10031031
name := p.lexer.Identifier.String

internal/js_parser/ts_parser_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2194,6 +2194,13 @@ func TestTSTypeOnlyExport(t *testing.T) {
21942194
expectPrintedTS(t, "{ let Foo; } export {Foo}", "{\n let Foo;\n}\nexport {};\n")
21952195
expectPrintedTS(t, "export {Foo}", "export {};\n")
21962196
expectParseError(t, "export {Foo}", "<stdin>: ERROR: \"Foo\" is not declared in this file\n")
2197+
2198+
// This is a syntax error in TypeScript, but we parse it anyway because
2199+
// people blame esbuild when it doesn't parse. It's silently discarded
2200+
// because we always discard all type annotations (even invalid ones).
2201+
expectPrintedTS(t, "export type * from 'foo'\nbar", "bar;\n")
2202+
expectPrintedTS(t, "export type * as foo from 'bar'; foo", "foo;\n")
2203+
expectPrintedTS(t, "export type * as 'f o' from 'bar'; foo", "foo;\n")
21972204
}
21982205

21992206
func TestTSOptionalChain(t *testing.T) {

0 commit comments

Comments
 (0)