Repository navigation
Re-scan '<<' when parsing type arguments in heritage clauses, typeof queries, and JSX - #64716
Open
ahmad65saad wants to merge 3 commits into
Open
ahmad65saad wants to merge 3 commits into
ahmad65saad wants to merge 3 commits into
Conversation
parseTypeArguments only checked for a '<' token, so a type argument list whose first type starts with '<' (e.g. a generic function type) was scanned as '<<' and never parsed. This affected heritage clauses, typeof type queries, and JSX opening elements. Re-scan the token first, as the type reference and expression paths already do. In a typeof type query, '<<' can also be a left shift following a type in an expression, as in `x as typeof y << 1`, which already compiles. There the type arguments are parsed speculatively and only kept if they parse without errors; otherwise the '<<' is left alone. Fixes microsoft#47410
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The newly affected JSDoc parsing path lacks regression coverage.
1 open finding
What changed in this PR
Fixes parsing of generic function types beginning with << in type arguments while preserving left-shift expressions.
Changes:
- Re-scans
<<when parsing type arguments. - Speculatively handles ambiguous
typeofqueries. - Adds regression coverage and baselines.
| File | Description |
|---|---|
tsc/internal/parser/parser.go |
Updates type-argument parsing and ambiguity handling. |
tsc/testdata/tests/cases/compiler/parseGenericArrowRatherThanLeftShift2.tsx |
Adds parser regression cases. |
tsc/testdata/baselines/reference/compiler/parseGenericArrowRatherThanLeftShift2.types |
Records inferred types. |
tsc/testdata/baselines/reference/compiler/parseGenericArrowRatherThanLeftShift2.symbols |
Records resolved symbols. |
tsc/testdata/baselines/reference/compiler/parseGenericArrowRatherThanLeftShift2.js |
Records emitted JavaScript. |
🧠 Review effort: Balanced
|
|
||
| func (p *Parser) parseTypeArguments() *ast.NodeList { | ||
| if p.token == ast.KindLessThanToken { | ||
| if p.reScanLessThanToken() == ast.KindLessThanToken { |
Author
|
@microsoft-github-policy-service agree |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Fixes #47410
The scanner produces
<<as a single token, and the parser is expected to callreScanLessThanToken()wherever a<may open a type argument list.parseTypeArgumentsOfTypeReferenceandtryParseTypeArgumentsInExpressionalready do this, butparseTypeArgumentsonly checked for<. So when the first type argument itself starts with<(e.g. a generic function type), the list was never parsed and the rest was misread as a shift/relational expression:Fix
parseTypeArgumentsnow re-scans<<before checking for<. This covers heritage clauses (parseExpressionWithTypeArguments) and JSX opening/self-closing elements. In those positions<<can't be a left shift, so no valid code changes meaning. JSDoc@augments/@implementsalso go throughparseTypeArguments, but the JSDoc scanner never produces<<there, so they already worked;jsdocAugments_genericFunctionTypeArgument.tspins that (its baselines are identical with and without this change).typeoftype queries are the exception: there<<can legitimately be a left shift after a type in an expression, e.g.a as typeof x << 1, which compiles today. So inparseTypeQuery, when the token is<<, the type arguments are parsed speculatively (mark/rewind, same diagnostics-count check asskipParameterStart) and dropped if they don't parse cleanly.Tests
New test
parseGenericArrowRatherThanLeftShift2.tsxcovers each position above, plus the instantiation/call expression forms, and ordinary<<shift expressions (including inside JSX attributes and afteras typeof/satisfies typeof) to make sure they still parse as shifts. The first commit adds the test with the old (erroring) baselines so the change is visible in the second commit's diff. No other baselines changed.Note: the JSDoc test's baseline includes TS8023 (
JSDoc '@augments A' does not match the 'extends A' clause). That also happens onmainwithout this change:checkJSDocAugmentsTagMatchesExtendscompares the twoA<<T>(x: T) => T>types withisTypeIdenticalTo, and the separately written generic function types aren't identical. It's a checker issue unrelated to parsing, so I left it out of scope here.npx hereby test✅npx hereby lint✅npx hereby check:format✅npx hereby validate✅This PR was written in part with the assistance of generative AI (Claude).