@@ -5732,20 +5732,18 @@ namespace ts {
5732
5732
case SyntaxKind.NoSubstitutionTemplateLiteral: // foo<T> `...`
5733
5733
case SyntaxKind.TemplateHead: // foo<T> `...${100}...`
5734
5734
return true;
5735
- // Technically strict mode reserved words are valid identifiers in non-strict mode, and can thus
5736
- // start an expression. However, when they follow a type argument list and are immediately
5737
- // preceded by a line break, we don't consider them expression starters.
5738
- // This supports a semicolon-less style for code like the following:
5739
- //
5740
- // let specialFoo = foo<string>
5741
- // let value = ...
5742
- //
5743
- case SyntaxKind.InterfaceKeyword:
5744
- case SyntaxKind.LetKeyword:
5745
- return scanner.hasPrecedingLineBreak();
5735
+ // A type argument list followed by `<` never makes sense, and a type argument list followed
5736
+ // by `>` is ambiguous with a (re-scanned) `>>` operator, so we disqualify both.
5737
+ case SyntaxKind.LessThanToken:
5738
+ case SyntaxKind.GreaterThanToken:
5739
+ // In this context, `+` and `-` are unary operators, not binary operators.
5740
+ case SyntaxKind.PlusToken:
5741
+ case SyntaxKind.MinusToken:
5742
+ return false;
5746
5743
}
5747
- // Consider something a type argument list only if the following token can't start an expression.
5748
- return !isStartOfExpression();
5744
+ // We favor the type argument list interpretation when it is immediately followed by
5745
+ // a line break, a binary operator, or something that can't start an expression.
5746
+ return scanner.hasPrecedingLineBreak() || isBinaryOperator() || !isStartOfExpression();
5749
5747
}
5750
5748
5751
5749
function parsePrimaryExpression(): PrimaryExpression {
0 commit comments