Skip to content

Commit

Permalink
fix #3574: ts type parser bug with infer + extends
Browse files Browse the repository at this point in the history
  • Loading branch information
evanw committed Jan 3, 2024
1 parent f6eae0c commit 35c0d65
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 2 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## Unreleased

* Fix a bug with TypeScript type parsing ([#3574](https://github.com/evanw/esbuild/issues/3574))

This release fixes a bug with esbuild's TypeScript parser where a conditional type containing a union type that ends with an infer type that ends with a constraint could fail to parse. This was caused by the "don't parse a conditional type" flag not getting passed through the union type parser. Here's an example of valid TypeScript code that previously failed to parse correctly:

```ts
type InferUnion<T> = T extends { a: infer U extends number } | infer U extends number ? U : never
```
## 0.19.11
* Fix TypeScript-specific class transform edge case ([#3559](https://github.com/evanw/esbuild/issues/3559))
Expand Down
4 changes: 2 additions & 2 deletions internal/js_parser/ts_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,14 +482,14 @@ loop:
return
}
p.lexer.Next()
p.skipTypeScriptType(js_ast.LBitwiseOr)
p.skipTypeScriptTypeWithFlags(js_ast.LBitwiseOr, flags)

case js_lexer.TAmpersand:
if level >= js_ast.LBitwiseAnd {
return
}
p.lexer.Next()
p.skipTypeScriptType(js_ast.LBitwiseAnd)
p.skipTypeScriptTypeWithFlags(js_ast.LBitwiseAnd, flags)

case js_lexer.TExclamation:
// A postfix "!" is allowed in JSDoc types in TypeScript, which are only
Expand Down
4 changes: 4 additions & 0 deletions internal/js_parser/ts_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,10 @@ func TestTSTypes(t *testing.T) {
expectPrintedTS(t, "type Foo = Bar extends [infer T extends string] ? T : null", "")
expectPrintedTS(t, "type Foo = {} extends infer T extends {} ? A<T> : never", "")
expectPrintedTS(t, "type Foo = {} extends (infer T extends {}) ? A<T> : never", "")
expectPrintedTS(t, "type Foo<T> = T extends { a: infer U extends number } | { b: infer U extends number } ? U : never", "")
expectPrintedTS(t, "type Foo<T> = T extends { a: infer U extends number } & { b: infer U extends number } ? U : never", "")
expectPrintedTS(t, "type Foo<T> = T extends { a: infer U extends number } | infer U extends number ? U : never", "")
expectPrintedTS(t, "type Foo<T> = T extends { a: infer U extends number } & infer U extends number ? U : never", "")
expectPrintedTS(t, "let x: A extends B<infer C extends D> ? D : never", "let x;\n")
expectPrintedTS(t, "let x: A extends B<infer C extends D ? infer C : never> ? D : never", "let x;\n")
expectPrintedTS(t, "let x: ([e1, e2, ...es]: any) => any", "let x;\n")
Expand Down

0 comments on commit 35c0d65

Please sign in to comment.