Repository: alangpierce/sucrase
Pull request #719 (2022-07-12 22:56:39)

Port babel-parser changes from 2022-05-01 to 2022-06-27
Instructions: https://github.com/alangpierce/sucrase/wiki/Porting-changes-from-Babel's-parser

0e6900d771 Fix parsing ts type casts and nested patterns in destructuring (#14500)
🚫 It looks like this only affects AST transformation and error handling, so not relevant for Sucrase.

e29e915d2e fix: allow liberal named type-as imports (#14522)
✅ Sucrase already had looser checking and is not affected, but I added a test anyway.

47a3240c39 v7.17.12
🚫 Release only.

9156230e68 Fix parsing of `<` after object literals with the `jsx` plugin (#14557)
🚫 Sucrase isn't affected by this issue, seems to be a bug in Babel implementation details that were removed for Sucrase.

d6ff91940f [ts] Add support for instantiation expressions (#14457)
✅ Implemented by adding back the startsExpr flag on tokens and filling it in based on Babel's definitions. Used updated logic from 2ca44e4951 below. Also implemented typeof and new cases similarly to Babel.

59d24a45d9 [ts 4.7] Support `extends` constraints for `infer` (#14476)
✅ Implemented using logic similar to Babel and TS. Sadly, this requires adding a new state field, which slows down all snapshot/restore and adds some extra work to all type parsing.

6415f091ff [ts 4.7] Support optional variance annotations (#14359)
✅ Implemented more directly without using the modifiers system, which didn't seem necessary here.

2d5f5ad7fd v7.18.0
🚫 Release only.

f8cf03c067 Fix typo in moduleAttributesVerionPluginOption (#14584)
🚫 Typo not in Sucrase.

4d4db2a95b v7.18.3
🚫 Relase only.

8967ccbdd8 fix: `loc.index` of some nodes is wrongly enumerable. (#14595)
🚫 AST only.

e8c4b78330 [ts] FIx parsing of nested `extends` type in arrow type (#14604)
✅ Set inDisallowConditionalTypesContext for that code path and added test.

64b30c673e Update failing Babel 8 parser fixture (#14615)
🚫 Babel internal change.

5419d84da4 v7.18.4
🚫 Release only.

52cdab724d [babel 8] Recover from error when parsing `<T>() => {}</T>` (#14616)
🚫 Appears to only affect error handling.

dd75b027e4 feat: Automatically generate test results that do not exist (#14592)
🚫 Babel internal change.

3b206e11a7 Enable test `variance-annotations-with-jsx` with babel8 (#14626)
🚫 Babel internal change.

352d4d2246 v7.18.5
🚫 Release only.

f8785e973b Rename Babel parser decorator tests (#14665)
🚫 Babel internal change.

2ca44e4951 [ts] Allow `...<...>` followed by newline or binary operator (#14636)
✅ Implemented with same logic as Babel.

f0ec180eb7 Enforce `_foo.default || _foo` to import lib files in tests (#14673)
🚫 Babel internal change.

4c3365f6bd Enforce setting `type` in `package.json` (#14675)
🚫 Babel internal change.

e8dce41083 JSON modules should be imported with default (#14668)
🚫 Only affects validation, so not relevant for Sucrase.

e4e700ebe5 [ts] Disallow property access after instantiation expression (#14650)
🚫 Only affects validation, so not relevant for Sucrase.

7c91b80f31 v7.18.6
🚫 Release only.

codecov[bot]: # [Codecov](https://codecov.io/gh/alangpierce/sucrase/pull/719?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) Report
> Merging [#719](https://codecov.io/gh/alangpierce/sucrase/pull/719?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) (8166abb) into [main](https://codecov.io/gh/alangpierce/sucrase/commit/173e4fefc2288a0d38d89dcd9ce8c21acc175f81?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) (173e4fe) will **increase** coverage by `0.16%`.
> The diff coverage is `98.61%`.

```diff
@@            Coverage Diff             @@
##             main     #719      +/-   ##
==========================================
+ Coverage   86.86%   87.03%   +0.16%     
==========================================
  Files          54       54              
  Lines        5665     5700      +35     
  Branches     1333     1341       +8     
==========================================
+ Hits         4921     4961      +40     
+ Misses        472      470       -2     
+ Partials      272      269       -3     
```


| [Impacted Files](https://codecov.io/gh/alangpierce/sucrase/pull/719?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce) | Coverage Δ | |
|---|---|---|
| [src/parser/tokenizer/readWordTree.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci90b2tlbml6ZXIvcmVhZFdvcmRUcmVlLnRz) | `100.00% <ø> (ø)` | |
| [src/transformers/JSXTransformer.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3RyYW5zZm9ybWVycy9KU1hUcmFuc2Zvcm1lci50cw==) | `97.16% <96.15%> (+0.63%)` | :arrow_up: |
| [src/parser/plugins/jsx/xhtml.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci9wbHVnaW5zL2pzeC94aHRtbC50cw==) | `100.00% <100.00%> (ø)` | |
| [src/parser/plugins/typescript.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci9wbHVnaW5zL3R5cGVzY3JpcHQudHM=) | `87.23% <100.00%> (+0.83%)` | :arrow_up: |
| [src/parser/tokenizer/index.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci90b2tlbml6ZXIvaW5kZXgudHM=) | `86.05% <100.00%> (+0.09%)` | :arrow_up: |
| [src/parser/tokenizer/keywords.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci90b2tlbml6ZXIva2V5d29yZHMudHM=) | `100.00% <100.00%> (ø)` | |
| [src/parser/tokenizer/state.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci90b2tlbml6ZXIvc3RhdGUudHM=) | `100.00% <100.00%> (ø)` | |
| [src/parser/traverser/expression.ts](https://codecov.io/gh/alangpierce/sucrase/pull/719/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce#diff-c3JjL3BhcnNlci90cmF2ZXJzZXIvZXhwcmVzc2lvbi50cw==) | `88.41% <100.00%> (-0.03%)` | :arrow_down: |

:mega: Codecov can now indicate which changes are the most critical in Pull Requests. [Learn more](https://about.codecov.io/product/feature/runtime-insights/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Alan+Pierce)

github-actions[bot]: ## Benchmark results
**Before this PR:** 292.6 thousand lines per second
**After this PR:**  288.5 thousand lines per second

**Measured change:** 1.42% slower (2.28% slower to 0.28% faster)
**Summary:** Likely no significant difference

Patch:
diff --git a/generator/generateReadWordTree.ts b/generator/generateReadWordTree.ts
index ee2e3f0..80e8959 100644
--- a/generator/generateReadWordTree.ts
+++ b/generator/generateReadWordTree.ts
@@ -65,9 +65,10 @@ const CONTEXTUAL_KEYWORDS = [
   "namespace",
   "of",
   "opaque",
+  "out",
+  "override",
   "private",
   "protected",
-  "override",
   "proto",
   "public",
   "readonly",
diff --git a/generator/generateTokenTypes.ts b/generator/generateTokenTypes.ts
index 23c4b66..b260f4d 100644
--- a/generator/generateTokenTypes.ts
+++ b/generator/generateTokenTypes.ts
@@ -1,6 +1,7 @@
 const isAssign = true;
 const prefix = true;
 const postfix = true;
+const startsExpr = true;
 
 interface TokenOptions {
   keyword?: string;
@@ -8,6 +9,7 @@ interface TokenOptions {
   isAssign?: boolean;
   prefix?: boolean;
   postfix?: boolean;
+  startsExpr?: boolean;
   binop?: number;
 }
 
@@ -18,6 +20,7 @@ class TokenType {
   isAssign: boolean;
   prefix: boolean;
   postfix: boolean;
+  startsExpr: boolean;
   binop: number | null;
 
   constructor(label: string, conf: TokenOptions = {}) {
@@ -27,6 +30,7 @@ class TokenType {
     this.isAssign = !!conf.isAssign;
     this.prefix = !!conf.prefix;
     this.postfix = !!conf.postfix;
+    this.startsExpr = !!conf.startsExpr;
     this.binop = conf.binop === 0 ? 0 : conf.binop || null;
   }
 }
@@ -40,28 +44,28 @@ class KeywordTokenType extends TokenType {
 }
 
 class BinopTokenType extends TokenType {
-  constructor(name: string, prec: number) {
-    super(name, {binop: prec});
+  constructor(name: string, prec: number, options: TokenOptions = {}) {
+    super(name, {binop: prec, ...options});
   }
 }
 
 const types = {
-  num: new TokenType("num"),
-  bigint: new TokenType("bigint"),
-  decimal: new TokenType("decimal"),
-  regexp: new TokenType("regexp"),
-  string: new TokenType("string"),
-  name: new TokenType("name"),
+  num: new TokenType("num", {startsExpr}),
+  bigint: new TokenType("bigint", {startsExpr}),
+  decimal: new TokenType("decimal", {startsExpr}),
+  regexp: new TokenType("regexp", {startsExpr}),
+  string: new TokenType("string", {startsExpr}),
+  name: new TokenType("name", {startsExpr}),
   eof: new TokenType("eof"),
 
   // Punctuation token types.
-  bracketL: new TokenType("["),
+  bracketL: new TokenType("[", {startsExpr}),
   bracketR: new TokenType("]"),
-  braceL: new TokenType("{"),
-  braceBarL: new TokenType("{|"),
+  braceL: new TokenType("{", {startsExpr}),
+  braceBarL: new TokenType("{|", {startsExpr}),
   braceR: new TokenType("}"),
   braceBarR: new TokenType("|}"),
-  parenL: new TokenType("("),
+  parenL: new TokenType("(", {startsExpr}),
   parenR: new TokenType(")"),
   comma: new TokenType(","),
   semi: new TokenType(";"),
@@ -74,18 +78,18 @@ const types = {
   template: new TokenType("template"),
   ellipsis: new TokenType("..."),
   backQuote: new TokenType("`"),
-  dollarBraceL: new TokenType("${"),
+  dollarBraceL: new TokenType("${", {startsExpr}),
   at: new TokenType("@"),
-  hash: new TokenType("#"),
+  hash: new TokenType("#", {startsExpr}),
 
   eq: new TokenType("=", {isAssign}),
   assign: new TokenType("_=", {isAssign}),
   // Mark the token as either prefix or postfix for the parser; we later assign
   // based on what we find.
-  preIncDec: new TokenType("++/--", {prefix, postfix}),
-  postIncDec: new TokenType("++/--", {prefix, postfix}),
-  bang: new TokenType("!", {prefix}),
-  tilde: new TokenType("~", {prefix}),
+  preIncDec: new TokenType("++/--", {prefix, postfix, startsExpr}),
+  postIncDec: new TokenType("++/--", {prefix, postfix, startsExpr}),
+  bang: new TokenType("!", {prefix, startsExpr}),
+  tilde: new TokenType("~", {prefix, startsExpr}),
   pipeline: new BinopTokenType("|>", 0),
   nullishCoalescing: new BinopTokenType("??", 1),
   logicalOR: new BinopTokenType("||", 1),
@@ -99,18 +103,18 @@ const types = {
   relationalOrEqual: new BinopTokenType("<=/>=", 7),
   bitShiftL: new BinopTokenType("<<", 8),
   bitShiftR: new BinopTokenType(">>/>>>", 8),
-  plus: new TokenType("+", {binop: 9, prefix}),
-  minus: new TokenType("-", {binop: 9, prefix}),
-  modulo: new BinopTokenType("%", 10),
+  plus: new TokenType("+", {binop: 9, prefix, startsExpr}),
+  minus: new TokenType("-", {binop: 9, prefix, startsExpr}),
+  modulo: new BinopTokenType("%", 10, {startsExpr}),
   star: new BinopTokenType("*", 10),
   slash: new BinopTokenType("/", 10),
   exponent: new TokenType("**", {binop: 11, rightAssociative: true}),
 
   jsxName: new TokenType("jsxName"),
   jsxText: new TokenType("jsxText"),
-  jsxTagStart: new TokenType("jsxTagStart"),
+  jsxTagStart: new TokenType("jsxTagStart", {startsExpr}),
   jsxTagEnd: new TokenType("jsxTagEnd"),
-  typeParameterStart: new TokenType("typeParameterStart"),
+  typeParameterStart: new TokenType("typeParameterStart", {startsExpr}),
   nonNullAssertion: new TokenType("nonNullAssertion"),
 
   // keywords
@@ -124,52 +128,52 @@ const types = {
   _else: new KeywordTokenType("else"),
   _finally: new KeywordTokenType("finally"),
   _for: new KeywordTokenType("for"),
-  _function: new KeywordTokenType("function"),
+  _function: new KeywordTokenType("function", {startsExpr}),
   _if: new KeywordTokenType("if"),
   _return: new KeywordTokenType("return"),
   _switch: new KeywordTokenType("switch"),
-  _throw: new KeywordTokenType("throw", {prefix}),
+  _throw: new KeywordTokenType("throw", {prefix, startsExpr}),
   _try: new KeywordTokenType("try"),
   _var: new KeywordTokenType("var"),
   _let: new KeywordTokenType("let"),
   _const: new KeywordTokenType("const"),
   _while: new KeywordTokenType("while"),
   _with: new KeywordTokenType("with"),
-  _new: new KeywordTokenType("new"),
-  _this: new KeywordTokenType("this"),
-  _super: new KeywordTokenType("super"),
-  _class: new KeywordTokenType("class"),
+  _new: new KeywordTokenType("new", {startsExpr}),
+  _this: new KeywordTokenType("this", {startsExpr}),
+  _super: new KeywordTokenType("super", {startsExpr}),
+  _class: new KeywordTokenType("class", {startsExpr}),
   _extends: new KeywordTokenType("extends"),
   _export: new KeywordTokenType("export"),
-  _import: new KeywordTokenType("import"),
-  _yield: new KeywordTokenType("yield"),
-  _null: new KeywordTokenType("null"),
-  _true: new KeywordTokenType("true"),
-  _false: new KeywordTokenType("false"),
+  _import: new KeywordTokenType("import", {startsExpr}),
+  _yield: new KeywordTokenType("yield", {startsExpr}),
+  _null: new KeywordTokenType("null", {startsExpr}),
+  _true: new KeywordTokenType("true", {startsExpr}),
+  _false: new KeywordTokenType("false", {startsExpr}),
   _in: new KeywordTokenType("in", {binop: 7}),
   _instanceof: new KeywordTokenType("instanceof", {binop: 7}),
-  _typeof: new KeywordTokenType("typeof", {prefix}),
-  _void: new KeywordTokenType("void", {prefix}),
-  _delete: new KeywordTokenType("delete", {prefix}),
+  _typeof: new KeywordTokenType("typeof", {prefix, startsExpr}),
+  _void: new KeywordTokenType("void", {prefix, startsExpr}),
+  _delete: new KeywordTokenType("delete", {prefix, startsExpr}),
 
   // Other keywords
-  _async: new KeywordTokenType("async"),
-  _get: new KeywordTokenType("get"),
-  _set: new KeywordTokenType("set"),
+  _async: new KeywordTokenType("async", {startsExpr}),
+  _get: new KeywordTokenType("get", {startsExpr}),
+  _set: new KeywordTokenType("set", {startsExpr}),
 
   // TypeScript keywords
-  _declare: new KeywordTokenType("declare"),
-  _readonly: new KeywordTokenType("readonly"),
-  _abstract: new KeywordTokenType("abstract"),
-  _static: new KeywordTokenType("static"),
+  _declare: new KeywordTokenType("declare", {startsExpr}),
+  _readonly: new KeywordTokenType("readonly", {startsExpr}),
+  _abstract: new KeywordTokenType("abstract", {startsExpr}),
+  _static: new KeywordTokenType("static", {startsExpr}),
   _public: new KeywordTokenType("public"),
   _private: new KeywordTokenType("private"),
   _protected: new KeywordTokenType("protected"),
   _override: new KeywordTokenType("override"),
-  _as: new KeywordTokenType("as"),
-  _enum: new KeywordTokenType("enum"),
-  _type: new KeywordTokenType("type"),
-  _implements: new KeywordTokenType("implements"),
+  _as: new KeywordTokenType("as", {startsExpr}),
+  _enum: new KeywordTokenType("enum", {startsExpr}),
+  _type: new KeywordTokenType("type", {startsExpr}),
+  _implements: new KeywordTokenType("implements", {startsExpr}),
 };
 
 export default function generateTokenTypes(): string {
@@ -195,6 +199,7 @@ export enum TokenType {
   IS_RIGHT_ASSOCIATIVE = 1 << 6,
   IS_PREFIX = 1 << 7,
   IS_POSTFIX = 1 << 8,
+  IS_EXPRESSION_START = 1 << 9,
 
 `;
   // Precedence 0 means not an operator; otherwise it is a positive number up to 12.
@@ -204,7 +209,8 @@ export enum TokenType {
   const IS_RIGHT_ASSOCIATIVE = 1 << 6;
   const IS_PREFIX = 1 << 7;
   const IS_POSTFIX = 1 << 8;
-  const TOKEN_INDEX = 1 << 9;
+  const IS_EXPRESSION_START = 1 << 9;
+  const TOKEN_INDEX = 1 << 10;
 
   let count = 0;
   for (const [name, tokenType] of Object.entries(types)) {
@@ -236,6 +242,10 @@ export enum TokenType {
       value |= IS_POSTFIX;
       descriptions.push("postfix");
     }
+    if (tokenType.startsExpr) {
+      value |= IS_EXPRESSION_START;
+      descriptions.push("startsExpr");
+    }
     code += `  ${name} = ${value}, // ${descriptions.join(" ")}\n`;
     count++;
   }
diff --git a/src/parser/plugins/typescript.ts b/src/parser/plugins/typescript.ts
index 966e119..1095061 100644
--- a/src/parser/plugins/typescript.ts
+++ b/src/parser/plugins/typescript.ts
@@ -177,6 +177,9 @@ function tsParseTypeQuery(): void {
   } else {
     tsParseEntityName();
   }
+  if (!hasPrecedingLineBreak() && match(tt.lessThan)) {
+    tsParseTypeArguments();
+  }
 }
 
 function tsParseImportType(): void {
@@ -193,7 +196,16 @@ function tsParseImportType(): void {
 }
 
 function tsParseTypeParameter(): void {
-  parseIdentifier();
+  const hadIn = eat(tt._in);
+  const hadOut = eatContextual(ContextualKeyword._out);
+  if ((hadIn || hadOut) && !match(tt.name)) {
+    // The "in" or "out" keyword must have actually been the type parameter
+    // name, so set it as the name.
+    state.tokens[state.tokens.length - 1].type = tt.name;
+  } else {
+    parseIdentifier();
+  }
+
   if (eat(tt._extends)) {
     tsParseType();
   }
@@ -458,7 +470,10 @@ function tsParseFunctionOrConstructorType(type: FunctionType): void {
   if (type === FunctionType.TSConstructorType || type === FunctionType.TSAbstractConstructorType) {
     expect(tt._new);
   }
+  const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext;
+  state.inDisallowConditionalTypesContext = false;
   tsFillSignature(tt.arrow);
+  state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext;
 }
 
 function tsParseNonArrayType(): void {
@@ -537,6 +552,19 @@ function tsParseArrayTypeOrHigher(): void {
 function tsParseInferType(): void {
   expectContextual(ContextualKeyword._infer);
   parseIdentifier();
+  if (match(tt._extends)) {
+    // Infer type constraints introduce an ambiguity about whether the "extends"
+    // is a constraint for this infer type or is another conditional type.
+    const snapshot = state.snapshot();
+    expect(tt._extends);
+    const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext;
+    state.inDisallowConditionalTypesContext = true;
+    tsParseType();
+    state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext;
+    if (state.error || (!state.inDisallowConditionalTypesContext && match(tt.question))) {
+      state.restoreFromSnapshot(snapshot);
+    }
+  }
 }
 
 function tsParseTypeOperatorOrHigher(): void {
@@ -550,7 +578,10 @@ function tsParseTypeOperatorOrHigher(): void {
   } else if (isContextual(ContextualKeyword._infer)) {
     tsParseInferType();
   } else {
+    const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext;
+    state.inDisallowConditionalTypesContext = false;
     tsParseArrayTypeOrHigher();
+    state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext;
   }
 }
 
@@ -719,11 +750,15 @@ export function tsParseTypeAnnotation(): void {
 
 export function tsParseType(): void {
   tsParseNonConditionalType();
-  if (hasPrecedingLineBreak() || !eat(tt._extends)) {
+  if (state.inDisallowConditionalTypesContext || hasPrecedingLineBreak() || !eat(tt._extends)) {
     return;
   }
   // extends type
+  const oldInDisallowConditionalTypesContext = state.inDisallowConditionalTypesContext;
+  state.inDisallowConditionalTypesContext = true;
   tsParseNonConditionalType();
+  state.inDisallowConditionalTypesContext = oldInDisallowConditionalTypesContext;
+
   expect(tt.question);
   // true type
   tsParseType();
@@ -1206,7 +1241,16 @@ export function tsParseSubscript(
     } else if (match(tt.backQuote)) {
       // Tagged template with a type argument.
       parseTemplate();
-    } else {
+    } else if (
+      // a<b>>c is not (a<b>)>c, but a<(b>>c)
+      state.type === tt.greaterThan ||
+      // a<b>c is (a<b)>c
+      (state.type !== tt.parenL &&
+        Boolean(state.type & TokenType.IS_EXPRESSION_START) &&
+        !hasPrecedingLineBreak())
+    ) {
+      // Bail out. We have something like a<b>c, which is not an expression with
+      // type arguments but an (a < b) > c comparison.
       unexpected();
     }
 
@@ -1229,19 +1273,6 @@ export function tsParseSubscript(
   baseParseSubscript(startTokenIndex, noCalls, stopState);
 }
 
-export function tsStartParseNewArguments(): void {
-  if (match(tt.lessThan) || match(tt.bitShiftL)) {
-    // 99% certain this is `new C<T>();`. But may be `new C < T;`, which is also legal.
-    const snapshot = state.snapshot();
-
-    tsParseTypeArgumentsWithPossibleBitshift();
-
-    if (state.error) {
-      state.restoreFromSnapshot(snapshot);
-    }
-  }
-}
-
 export function tsTryParseExport(): boolean {
   if (eat(tt._import)) {
     // One of these cases:
diff --git a/src/parser/tokenizer/keywords.ts b/src/parser/tokenizer/keywords.ts
index 7095d70..b886bf7 100644
--- a/src/parser/tokenizer/keywords.ts
+++ b/src/parser/tokenizer/keywords.ts
@@ -24,6 +24,7 @@ export enum ContextualKeyword {
   _namespace,
   _of,
   _opaque,
+  _out,
   _override,
   _private,
   _protected,
diff --git a/src/parser/tokenizer/readWordTree.ts b/src/parser/tokenizer/readWordTree.ts
index a8ae384..3b947c0 100644
--- a/src/parser/tokenizer/readWordTree.ts
+++ b/src/parser/tokenizer/readWordTree.ts
@@ -5,7 +5,7 @@ import {TokenType as tt} from "./types";
 // prettier-ignore
 export const READ_WORD_TREE = new Int32Array([
   // ""
-  -1, 27, 783, 918, 1755, 2376, 2862, 3483, -1, 3699, -1, 4617, 4752, 4833, 5130, 5508, 5886, -1, 6426, 6885, 7479, 7911, 8073, 8235, -1, 8451, -1,
+  -1, 27, 783, 918, 1755, 2376, 2862, 3483, -1, 3699, -1, 4617, 4752, 4833, 5130, 5508, 5940, -1, 6480, 6939, 7533, 7965, 8127, 8289, -1, 8505, -1,
   // "a"
   -1, -1, 54, 243, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 432, -1, -1, -1, 675, -1, -1, -1,
   // "ab"
@@ -413,7 +413,7 @@ export const READ_WORD_TREE = new Int32Array([
   // "null"
   (tt._null << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "o"
-  -1, -1, -1, -1, -1, -1, 5535, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5562, -1, -1, -1, -1, -1, 5697, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, 5535, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5562, -1, -1, -1, -1, 5697, 5751, -1, -1, -1, -1,
   // "of"
   ContextualKeyword._of << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "op"
@@ -426,218 +426,222 @@ export const READ_WORD_TREE = new Int32Array([
   -1, -1, -1, -1, -1, 5670, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "opaque"
   ContextualKeyword._opaque << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  // "ou"
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5724, -1, -1, -1, -1, -1, -1,
+  // "out"
+  ContextualKeyword._out << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "ov"
-  -1, -1, -1, -1, -1, 5724, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 5778, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "ove"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5751, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5805, -1, -1, -1, -1, -1, -1, -1, -1,
   // "over"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5778, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5832, -1, -1, -1, -1, -1, -1, -1, -1,
   // "overr"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 5805, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 5859, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "overri"
-  -1, -1, -1, -1, 5832, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, 5886, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "overrid"
-  -1, -1, -1, -1, -1, 5859, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 5913, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "override"
   ContextualKeyword._override << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "p"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5913, -1, -1, 6291, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5967, -1, -1, 6345, -1, -1, -1, -1, -1,
   // "pr"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 5940, -1, -1, -1, -1, -1, 6075, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 5994, -1, -1, -1, -1, -1, 6129, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "pri"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5967, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6021, -1, -1, -1, -1,
   // "priv"
-  -1, 5994, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, 6048, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "priva"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6021, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6075, -1, -1, -1, -1, -1, -1,
   // "privat"
-  -1, -1, -1, -1, -1, 6048, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 6102, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "private"
   ContextualKeyword._private << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "pro"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6102, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6156, -1, -1, -1, -1, -1, -1,
   // "prot"
-  -1, -1, -1, -1, -1, 6129, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 6183, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6318, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "prote"
-  -1, -1, -1, 6156, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, 6210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "protec"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6183, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6237, -1, -1, -1, -1, -1, -1,
   // "protect"
-  -1, -1, -1, -1, -1, 6210, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 6264, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "protecte"
-  -1, -1, -1, -1, 6237, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, 6291, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "protected"
   ContextualKeyword._protected << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "proto"
   ContextualKeyword._proto << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "pu"
-  -1, -1, 6318, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, 6372, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "pub"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6399, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "publ"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 6372, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 6426, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "publi"
-  -1, -1, -1, 6399, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, 6453, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "public"
   ContextualKeyword._public << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "r"
-  -1, -1, -1, -1, -1, 6453, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 6507, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "re"
-  -1, 6480, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6642, -1, -1, 6777, -1, -1, -1, -1, -1, -1,
+  -1, 6534, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6696, -1, -1, 6831, -1, -1, -1, -1, -1, -1,
   // "rea"
-  -1, -1, -1, -1, 6507, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, 6561, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "read"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6534, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6588, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "reado"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6561, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6615, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "readon"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6588, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6642, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "readonl"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6615, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6669, -1,
   // "readonly"
   ContextualKeyword._readonly << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "req"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6669, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6723, -1, -1, -1, -1, -1,
   // "requ"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 6696, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 6750, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "requi"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6723, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6777, -1, -1, -1, -1, -1, -1, -1, -1,
   // "requir"
-  -1, -1, -1, -1, -1, 6750, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 6804, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "require"
   ContextualKeyword._require << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "ret"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6804, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6858, -1, -1, -1, -1, -1,
   // "retu"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6831, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6885, -1, -1, -1, -1, -1, -1, -1, -1,
   // "retur"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6858, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6912, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "return"
   (tt._return << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "s"
-  -1, -1, -1, -1, -1, 6912, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6966, 7101, -1, 7209, -1, 7344, -1,
+  -1, -1, -1, -1, -1, 6966, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7020, 7155, -1, 7263, -1, 7398, -1,
   // "se"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6939, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 6993, -1, -1, -1, -1, -1, -1,
   // "set"
   ContextualKeyword._set << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "st"
-  -1, 6993, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, 7047, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "sta"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7020, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7074, -1, -1, -1, -1, -1, -1,
   // "stat"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 7047, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 7101, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "stati"
-  -1, -1, -1, 7074, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, 7128, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "static"
   ContextualKeyword._static << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "su"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7128, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7182, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "sup"
-  -1, -1, -1, -1, -1, 7155, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 7209, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "supe"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7182, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7236, -1, -1, -1, -1, -1, -1, -1, -1,
   // "super"
   (tt._super << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "sw"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 7236, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 7290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "swi"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7263, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7317, -1, -1, -1, -1, -1, -1,
   // "swit"
-  -1, -1, -1, 7290, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, 7344, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "switc"
-  -1, -1, -1, -1, -1, -1, -1, -1, 7317, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, 7371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "switch"
   (tt._switch << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "sy"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7371, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7425, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "sym"
-  -1, -1, 7398, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, 7452, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "symb"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7425, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7479, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "symbo"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7452, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7506, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "symbol"
   ContextualKeyword._symbol << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "t"
-  -1, -1, -1, -1, -1, -1, -1, -1, 7506, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7668, -1, -1, -1, -1, -1, -1, 7776, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, 7560, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7722, -1, -1, -1, -1, -1, -1, 7830, -1,
   // "th"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 7533, -1, -1, -1, -1, -1, -1, -1, -1, 7587, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 7587, -1, -1, -1, -1, -1, -1, -1, -1, 7641, -1, -1, -1, -1, -1, -1, -1, -1,
   // "thi"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7560, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7614, -1, -1, -1, -1, -1, -1, -1,
   // "this"
   (tt._this << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "thr"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7614, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7668, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "thro"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7641, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7695, -1, -1, -1,
   // "throw"
   (tt._throw << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "tr"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7695, -1, -1, -1, 7749, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7749, -1, -1, -1, 7803, -1,
   // "tru"
-  -1, -1, -1, -1, -1, 7722, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 7776, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "true"
   (tt._true << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "try"
   (tt._try << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "ty"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7803, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7857, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "typ"
-  -1, -1, -1, -1, -1, 7830, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 7884, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "type"
-  ContextualKeyword._type << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7857, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  ContextualKeyword._type << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7911, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "typeo"
-  -1, -1, -1, -1, -1, -1, 7884, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, 7938, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "typeof"
   (tt._typeof << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "u"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7938, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7992, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "un"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 7965, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 8019, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "uni"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 7992, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8046, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "uniq"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8019, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8073, -1, -1, -1, -1, -1,
   // "uniqu"
-  -1, -1, -1, -1, -1, 8046, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 8100, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "unique"
   ContextualKeyword._unique << 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "v"
-  -1, 8100, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, 8154, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "va"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8127, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8181, -1, -1, -1, -1, -1, -1, -1, -1,
   // "var"
   (tt._var << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "vo"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 8181, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 8235, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "voi"
-  -1, -1, -1, -1, 8208, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, 8262, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "void"
   (tt._void << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "w"
-  -1, -1, -1, -1, -1, -1, -1, -1, 8262, 8370, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, 8316, 8424, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "wh"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 8289, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 8343, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "whi"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8316, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8370, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "whil"
-  -1, -1, -1, -1, -1, 8343, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 8397, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "while"
   (tt._while << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "wi"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8397, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8451, -1, -1, -1, -1, -1, -1,
   // "wit"
-  -1, -1, -1, -1, -1, -1, -1, -1, 8424, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, 8478, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "with"
   (tt._with << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "y"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, 8478, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, 8532, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "yi"
-  -1, -1, -1, -1, -1, 8505, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, 8559, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "yie"
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8532, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 8586, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "yiel"
-  -1, -1, -1, -1, 8559, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, 8613, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   // "yield"
   (tt._yield << 1) + 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
 ]);
diff --git a/src/parser/tokenizer/state.ts b/src/parser/tokenizer/state.ts
index a489b4f..43cff7c 100644
--- a/src/parser/tokenizer/state.ts
+++ b/src/parser/tokenizer/state.ts
@@ -18,6 +18,7 @@ export class StateSnapshot {
   constructor(
     readonly potentialArrowAt: number,
     readonly noAnonFunctionType: boolean,
+    readonly inDisallowConditionalTypesContext: boolean,
     readonly tokensLength: number,
     readonly scopesLength: number,
     readonly pos: number,
@@ -38,6 +39,9 @@ export default class State {
   // Used by Flow to handle an edge case involving function type parsing.
   noAnonFunctionType: boolean = false;
 
+  // Used by TypeScript to handle ambiguities when parsing conditional types.
+  inDisallowConditionalTypesContext: boolean = false;
+
   // Token store.
   tokens: Array<Token> = [];
 
@@ -70,6 +74,7 @@ export default class State {
     return new StateSnapshot(
       this.potentialArrowAt,
       this.noAnonFunctionType,
+      this.inDisallowConditionalTypesContext,
       this.tokens.length,
       this.scopes.length,
       this.pos,
@@ -86,6 +91,7 @@ export default class State {
   restoreFromSnapshot(snapshot: StateSnapshot): void {
     this.potentialArrowAt = snapshot.potentialArrowAt;
     this.noAnonFunctionType = snapshot.noAnonFunctionType;
+    this.inDisallowConditionalTypesContext = snapshot.inDisallowConditionalTypesContext;
     this.tokens.length = snapshot.tokensLength;
     this.scopes.length = snapshot.scopesLength;
     this.pos = snapshot.pos;
diff --git a/src/parser/tokenizer/types.ts b/src/parser/tokenizer/types.ts
index 9485807..36220b6 100644
--- a/src/parser/tokenizer/types.ts
+++ b/src/parser/tokenizer/types.ts
@@ -11,119 +11,120 @@ export enum TokenType {
   IS_RIGHT_ASSOCIATIVE = 1 << 6,
   IS_PREFIX = 1 << 7,
   IS_POSTFIX = 1 << 8,
+  IS_EXPRESSION_START = 1 << 9,
 
-  num = 0, // num
-  bigint = 512, // bigint
-  decimal = 1024, // decimal
-  regexp = 1536, // regexp
-  string = 2048, // string
-  name = 2560, // name
-  eof = 3072, // eof
-  bracketL = 3584, // [
-  bracketR = 4096, // ]
-  braceL = 4608, // {
-  braceBarL = 5120, // {|
-  braceR = 5632, // }
-  braceBarR = 6144, // |}
-  parenL = 6656, // (
-  parenR = 7168, // )
-  comma = 7680, // ,
-  semi = 8192, // ;
-  colon = 8704, // :
-  doubleColon = 9216, // ::
-  dot = 9728, // .
-  question = 10240, // ?
-  questionDot = 10752, // ?.
-  arrow = 11264, // =>
-  template = 11776, // template
-  ellipsis = 12288, // ...
-  backQuote = 12800, // `
-  dollarBraceL = 13312, // ${
-  at = 13824, // @
-  hash = 14336, // #
-  eq = 14880, // = isAssign
-  assign = 15392, // _= isAssign
-  preIncDec = 16256, // ++/-- prefix postfix
-  postIncDec = 16768, // ++/-- prefix postfix
-  bang = 17024, // ! prefix
-  tilde = 17536, // ~ prefix
-  pipeline = 17921, // |> prec:1
-  nullishCoalescing = 18434, // ?? prec:2
-  logicalOR = 18946, // || prec:2
-  logicalAND = 19459, // && prec:3
-  bitwiseOR = 19972, // | prec:4
-  bitwiseXOR = 20485, // ^ prec:5
-  bitwiseAND = 20998, // & prec:6
-  equality = 21511, // ==/!= prec:7
-  lessThan = 22024, // < prec:8
-  greaterThan = 22536, // > prec:8
-  relationalOrEqual = 23048, // <=/>= prec:8
-  bitShiftL = 23561, // << prec:9
-  bitShiftR = 24073, // >>/>>> prec:9
-  plus = 24714, // + prec:10 prefix
-  minus = 25226, // - prec:10 prefix
-  modulo = 25611, // % prec:11
-  star = 26123, // * prec:11
-  slash = 26635, // / prec:11
-  exponent = 27212, // ** prec:12 rightAssociative
-  jsxName = 27648, // jsxName
-  jsxText = 28160, // jsxText
-  jsxTagStart = 28672, // jsxTagStart
-  jsxTagEnd = 29184, // jsxTagEnd
-  typeParameterStart = 29696, // typeParameterStart
-  nonNullAssertion = 30208, // nonNullAssertion
-  _break = 30736, // break keyword
-  _case = 31248, // case keyword
-  _catch = 31760, // catch keyword
-  _continue = 32272, // continue keyword
-  _debugger = 32784, // debugger keyword
-  _default = 33296, // default keyword
-  _do = 33808, // do keyword
-  _else = 34320, // else keyword
-  _finally = 34832, // finally keyword
-  _for = 35344, // for keyword
-  _function = 35856, // function keyword
-  _if = 36368, // if keyword
-  _return = 36880, // return keyword
-  _switch = 37392, // switch keyword
-  _throw = 38032, // throw keyword prefix
-  _try = 38416, // try keyword
-  _var = 38928, // var keyword
-  _let = 39440, // let keyword
-  _const = 39952, // const keyword
-  _while = 40464, // while keyword
-  _with = 40976, // with keyword
-  _new = 41488, // new keyword
-  _this = 42000, // this keyword
-  _super = 42512, // super keyword
-  _class = 43024, // class keyword
-  _extends = 43536, // extends keyword
-  _export = 44048, // export keyword
-  _import = 44560, // import keyword
-  _yield = 45072, // yield keyword
-  _null = 45584, // null keyword
-  _true = 46096, // true keyword
-  _false = 46608, // false keyword
-  _in = 47128, // in prec:8 keyword
-  _instanceof = 47640, // instanceof prec:8 keyword
-  _typeof = 48272, // typeof keyword prefix
-  _void = 48784, // void keyword prefix
-  _delete = 49296, // delete keyword prefix
-  _async = 49680, // async keyword
-  _get = 50192, // get keyword
-  _set = 50704, // set keyword
-  _declare = 51216, // declare keyword
-  _readonly = 51728, // readonly keyword
-  _abstract = 52240, // abstract keyword
-  _static = 52752, // static keyword
-  _public = 53264, // public keyword
-  _private = 53776, // private keyword
-  _protected = 54288, // protected keyword
-  _override = 54800, // override keyword
-  _as = 55312, // as keyword
-  _enum = 55824, // enum keyword
-  _type = 56336, // type keyword
-  _implements = 56848, // implements keyword
+  num = 512, // num startsExpr
+  bigint = 1536, // bigint startsExpr
+  decimal = 2560, // decimal startsExpr
+  regexp = 3584, // regexp startsExpr
+  string = 4608, // string startsExpr
+  name = 5632, // name startsExpr
+  eof = 6144, // eof
+  bracketL = 7680, // [ startsExpr
+  bracketR = 8192, // ]
+  braceL = 9728, // { startsExpr
+  braceBarL = 10752, // {| startsExpr
+  braceR = 11264, // }
+  braceBarR = 12288, // |}
+  parenL = 13824, // ( startsExpr
+  parenR = 14336, // )
+  comma = 15360, // ,
+  semi = 16384, // ;
+  colon = 17408, // :
+  doubleColon = 18432, // ::
+  dot = 19456, // .
+  question = 20480, // ?
+  questionDot = 21504, // ?.
+  arrow = 22528, // =>
+  template = 23552, // template
+  ellipsis = 24576, // ...
+  backQuote = 25600, // `
+  dollarBraceL = 27136, // ${ startsExpr
+  at = 27648, // @
+  hash = 29184, // # startsExpr
+  eq = 29728, // = isAssign
+  assign = 30752, // _= isAssign
+  preIncDec = 32640, // ++/-- prefix postfix startsExpr
+  postIncDec = 33664, // ++/-- prefix postfix startsExpr
+  bang = 34432, // ! prefix startsExpr
+  tilde = 35456, // ~ prefix startsExpr
+  pipeline = 35841, // |> prec:1
+  nullishCoalescing = 36866, // ?? prec:2
+  logicalOR = 37890, // || prec:2
+  logicalAND = 38915, // && prec:3
+  bitwiseOR = 39940, // | prec:4
+  bitwiseXOR = 40965, // ^ prec:5
+  bitwiseAND = 41990, // & prec:6
+  equality = 43015, // ==/!= prec:7
+  lessThan = 44040, // < prec:8
+  greaterThan = 45064, // > prec:8
+  relationalOrEqual = 46088, // <=/>= prec:8
+  bitShiftL = 47113, // << prec:9
+  bitShiftR = 48137, // >>/>>> prec:9
+  plus = 49802, // + prec:10 prefix startsExpr
+  minus = 50826, // - prec:10 prefix startsExpr
+  modulo = 51723, // % prec:11 startsExpr
+  star = 52235, // * prec:11
+  slash = 53259, // / prec:11
+  exponent = 54348, // ** prec:12 rightAssociative
+  jsxName = 55296, // jsxName
+  jsxText = 56320, // jsxText
+  jsxTagStart = 57856, // jsxTagStart startsExpr
+  jsxTagEnd = 58368, // jsxTagEnd
+  typeParameterStart = 59904, // typeParameterStart startsExpr
+  nonNullAssertion = 60416, // nonNullAssertion
+  _break = 61456, // break keyword
+  _case = 62480, // case keyword
+  _catch = 63504, // catch keyword
+  _continue = 64528, // continue keyword
+  _debugger = 65552, // debugger keyword
+  _default = 66576, // default keyword
+  _do = 67600, // do keyword
+  _else = 68624, // else keyword
+  _finally = 69648, // finally keyword
+  _for = 70672, // for keyword
+  _function = 72208, // function keyword startsExpr
+  _if = 72720, // if keyword
+  _return = 73744, // return keyword
+  _switch = 74768, // switch keyword
+  _throw = 76432, // throw keyword prefix startsExpr
+  _try = 76816, // try keyword
+  _var = 77840, // var keyword
+  _let = 78864, // let keyword
+  _const = 79888, // const keyword
+  _while = 80912, // while keyword
+  _with = 81936, // with keyword
+  _new = 83472, // new keyword startsExpr
+  _this = 84496, // this keyword startsExpr
+  _super = 85520, // super keyword startsExpr
+  _class = 86544, // class keyword startsExpr
+  _extends = 87056, // extends keyword
+  _export = 88080, // export keyword
+  _import = 89616, // import keyword startsExpr
+  _yield = 90640, // yield keyword startsExpr
+  _null = 91664, // null keyword startsExpr
+  _true = 92688, // true keyword startsExpr
+  _false = 93712, // false keyword startsExpr
+  _in = 94232, // in prec:8 keyword
+  _instanceof = 95256, // instanceof prec:8 keyword
+  _typeof = 96912, // typeof keyword prefix startsExpr
+  _void = 97936, // void keyword prefix startsExpr
+  _delete = 98960, // delete keyword prefix startsExpr
+  _async = 99856, // async keyword startsExpr
+  _get = 100880, // get keyword startsExpr
+  _set = 101904, // set keyword startsExpr
+  _declare = 102928, // declare keyword startsExpr
+  _readonly = 103952, // readonly keyword startsExpr
+  _abstract = 104976, // abstract keyword startsExpr
+  _static = 106000, // static keyword startsExpr
+  _public = 106512, // public keyword
+  _private = 107536, // private keyword
+  _protected = 108560, // protected keyword
+  _override = 109584, // override keyword
+  _as = 111120, // as keyword startsExpr
+  _enum = 112144, // enum keyword startsExpr
+  _type = 113168, // type keyword startsExpr
+  _implements = 114192, // implements keyword startsExpr
 }
 export function formatTokenType(tokenType: TokenType): string {
   switch (tokenType) {
diff --git a/src/parser/traverser/expression.ts b/src/parser/traverser/expression.ts
index a3530df..3981489 100644
--- a/src/parser/traverser/expression.ts
+++ b/src/parser/traverser/expression.ts
@@ -39,7 +39,6 @@ import {
   tsParseType,
   tsParseTypeAssertion,
   tsStartParseAsyncArrowFromCallExpression,
-  tsStartParseNewArguments,
   tsStartParseObjPropValue,
 } from "../plugins/typescript";
 import {
@@ -715,15 +714,8 @@ function parseNew(): void {
     parseIdentifier();
     return;
   }
-  parseNoCallExpr();
-  eat(tt.questionDot);
-  parseNewArguments();
-}
-
-function parseNewArguments(): void {
-  if (isTypeScriptEnabled) {
-    tsStartParseNewArguments();
-  } else if (isFlowEnabled) {
+  parseNewCallee();
+  if (isFlowEnabled) {
     flowStartParseNewArguments();
   }
   if (eat(tt.parenL)) {
@@ -731,6 +723,11 @@ function parseNewArguments(): void {
   }
 }
 
+function parseNewCallee(): void {
+  parseNoCallExpr();
+  eat(tt.questionDot);
+}
+
 export function parseTemplate(): void {
   // Finish `, read quasi
   nextTemplateToken();


Test patch:
diff --git a/test/typescript-test.ts b/test/typescript-test.ts
index ab9613a..a657a9a 100644
--- a/test/typescript-test.ts
+++ b/test/typescript-test.ts
@@ -2796,6 +2796,17 @@ describe("typescript transform", () => {
     );
   });
 
+  it("allows type imports of keyword names", () => {
+    assertTypeScriptESMResult(
+      `
+      import {type default as Foo} from './Foo';
+    `,
+      `
+
+    `,
+    );
+  });
+
   it("allows static index signatures", () => {
     assertTypeScriptESMResult(
       `
@@ -3130,4 +3141,164 @@ describe("typescript transform", () => {
       {transforms: ["typescript"]},
     );
   });
+
+  it("handles TS instantiation expressions", () => {
+    assertResult(
+      `
+      const NumberSet = Set<number>;
+      const foo = new NumberSet();
+    `,
+      `
+      const NumberSet = Set;
+      const foo = new NumberSet();
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("distinguishes between instantiation expressions and greater-than", () => {
+    assertResult(
+      `
+      let notTypeArg = Array<number>3;
+      let typeArg = (Array<number>);
+      typeArg = ((Array<number>));
+      typeArg = Array<number>();
+      notTypeArg = Array<number>7;
+      typeArg = Array<number>
+      if (true) {}
+      notTypeArg = Array<number>>3;
+      notTypeArg = Array<number>true;
+      notTypeArg = Array<number>!true;
+      notTypeArg = Array<number>function foo() {};
+    `,
+      `
+      let notTypeArg = Array<number>3;
+      let typeArg = (Array);
+      typeArg = ((Array));
+      typeArg = Array();
+      notTypeArg = Array<number>7;
+      typeArg = Array
+      if (true) {}
+      notTypeArg = Array<number>>3;
+      notTypeArg = Array<number>true;
+      notTypeArg = Array<number>!true;
+      notTypeArg = Array<number>function foo() {};
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("allows new instantiation expressions", () => {
+    assertResult(
+      `
+      const a = new A < B > C;
+      const b = new A<B>;
+    `,
+      `
+      const a = new A < B > C;
+      const b = new A;
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("allows typeof expressions with instantiation expression type arguments", () => {
+    assertResult(
+      `
+      const f: typeof foo<number> = foo;
+    `,
+      `
+      const f = foo;
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("allows extends constraints on infer type variables", () => {
+    assertResult(
+      `
+      type FirstString<T> =
+        T extends [infer S extends string, ...unknown[]]
+            ? S
+            : never;
+    `,
+      `
+      
+
+
+
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("handles infer with a nested conditional type", () => {
+    assertResult(
+      `
+      type A = T extends (infer U extends number ? U : T) ? U : T;
+    `,
+      `
+      
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("properly disallows conditional types within extends type", () => {
+    assertResult(
+      `
+      type A = T extends infer U extends number ? 1 : 0;
+    `,
+      `
+      
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("allows nested conditional types within functions", () => {
+    assertResult(
+      `
+      type A = T extends (x: A extends B ? C : D) => void ? 1 : 0;
+    `,
+      `
+      
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("allows variance modifiers", () => {
+    assertResult(
+      `
+      interface A<in T> {}
+      interface B<out T> {}
+      interface C<in out T> {}
+      interface D<in out T extends number> {}
+      interface E<out> {}
+      interface F<out extends number> {}
+    `,
+      `
+      
+
+
+
+
+
+    `,
+      {transforms: ["typescript"]},
+    );
+  });
+
+  it("allows JSX that looks like variance modifiers", () => {
+    assertResult(
+      `
+      <in T>() => {}</in>
+    `,
+      `${JSX_PREFIX}
+      React.createElement('in', { T: true, ${devProps(2)}}, "() => "  )
+    `,
+      {transforms: ["typescript", "jsx"]},
+    );
+  });
 });