Skip to content

Keep nested JSDoc properties after a property with a missing name - #65022

Open
NullVoxPopuli wants to merge 1 commit into
microsoft:mainfrom
NullVoxPopuli:nvp/jsdoc-nested-property-recovery
Open

NullVoxPopuli wants to merge 1 commit into
microsoft:mainfrom
NullVoxPopuli:nvp/jsdoc-nested-property-recovery

Conversation

@NullVoxPopuli

Copy link
Copy Markdown

Fixes #65020

When a nested @property type does not parse, every nested property after it is lost. With this change they are kept, as they are in flat typedefs and in TS 6.

/**
 * @typedef Sig
 * @property {object} Args
 * @property {string} Args.name
 * @property {function(string)=} Args.onSave
 * @property {((v: string) => void)=} Args.onCancel
 */
  • Before: keyof Sig['Args'] is "name".
  • After: keyof Sig['Args'] is "" | "name" | "onCancel". The TS1005 on function( stays.

Cause

The type parse stops at (, so the name of the Args.onSave tag is a missing identifier. parseChildParameterOrPropertyTag reads a plain identifier name as the start of a new top-level property, so it ended the Args type literal there. Args.onSave and Args.onCancel were then parsed at the typedef level.

The fix skips that check when the name is missing, so the tag stays in the nested literal. That gives the same "" property that a flat typedef gets for the same tag.

Test

jsdocNestedPropertyTagInvalidType.ts has a nested and a flat typedef with the same broken property, and keyof checks in a .ts file. Without the fix it reports TS2322 and TS2339 for onCancel.

npx hereby test passes with no other baseline changes. hereby lint and hereby check:format pass.

🤖 Generated with Claude Code

When a nested @Property type does not parse, the name of that tag is
missing. The nested type literal then ended at that tag, so every later
nested property was lost. Flat typedefs already keep the later
properties.

Fixes microsoft#65020

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 29, 2026 20:09
@typescript-automation typescript-automation Bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Oct 29, 2026
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Oct 29, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

There are no active review issues requiring changes.

No open issues 🎉

What changed in this PR

Fixes #65020 by improving JSDoc error recovery in the native TypeScript parser so a malformed nested property no longer drops subsequent valid properties.

Changes:

  • Keeps property tags with missing names inside the nested type literal.
  • Adds a regression test comparing nested and flat typedef recovery.
  • Adds baselines confirming onCancel remains available while the expected TS1005 diagnostics remain.
File Description
tsc/​testdata/​tests/​cases/​compiler/​jsdocNestedPropertyTagInvalidType.ts Tests nested and flat property recovery and access to onCancel.
tsc/​testdata/​baselines/​reference/​compiler/​jsdocNestedPropertyTagInvalidType.types Records recovered property keys and callback types.
tsc/​testdata/​baselines/​reference/​compiler/​jsdocNestedPropertyTagInvalidType.symbols Records symbol resolution for the regression test.
tsc/​testdata/​baselines/​reference/​compiler/​jsdocNestedPropertyTagInvalidType.errors.txt Records expected syntax errors and no consumer-file errors.
tsc/​internal/​parser/​jsdoc.go Prevents missing property names from ending nested property parsing.

Review effort: Balanced

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

JSDoc: a nested @property with a type that does not parse drops every nested @property after it

2 participants