Skip to content

[docs-infra] Fix duplicate JSDoc in proptypes generation for merged declarations#48296

Merged
brijeshb42 merged 1 commit intomui:masterfrom
brijeshb42:fix-proptypes-generation
Apr 16, 2026
Merged

[docs-infra] Fix duplicate JSDoc in proptypes generation for merged declarations#48296
brijeshb42 merged 1 commit intomui:masterfrom
brijeshb42:fix-proptypes-generation

Conversation

@brijeshb42
Copy link
Copy Markdown
Contributor

@brijeshb42 brijeshb42 commented Apr 16, 2026

The getSymbolDocumentation function was introduced in #47685 to handle JSDoc merging across multiple TypeScript declarations. However, it unconditionally joined all unique JSDoc comments when a symbol had multiple declarations, which produced duplicated descriptions in the generated propTypes for interface declaration merging and module augmentation scenarios.

TypeScript treats JSDoc differently depending on how declarations combine:

  • Intersection types (type C = A & B): all constituent JSDoc are merged
  • Interface extends (interface Z extends X, Y): first parent's JSDoc wins
  • Interface override (interface W extends X { prop }): the override's JSDoc wins
  • Declaration merging / module augmentation: last declaration's JSDoc wins

The previous implementation treated all multi-declaration cases as intersections, concatenating distinct comments. This caused issues in downstream repos (e.g. mui-x) where module augmentation is used to extend interface props — the original and augmented JSDoc would both appear in the generated propTypes output.

The fix now uses parentType.isIntersection() to distinguish intersection types (where merging is correct) from declaration merging (where the last declaration should win), matching TypeScript's own behavior.

Added test cases for all four JSDoc resolution scenarios:

  • jsdoc-intersection: verifies both descriptions are merged
  • jsdoc-interface-extends: verifies first parent's description wins
  • jsdoc-interface-override: verifies override description wins
  • declaration-merging: verifies last (augmented) description wins

The change doesn't affect anythin on this repo but does create some changes in X when run where the above 4 cases are encountered.

@brijeshb42 brijeshb42 added the scope: docs-infra Involves the docs-infra product (https://www.notion.so/mui-org/b9f676062eb94747b6768209f7751305). label Apr 16, 2026
@brijeshb42 brijeshb42 changed the title [code-infra] Fix duplicate JSDoc in proptypes generation for merged declarations [docs-infra] Fix duplicate JSDoc in proptypes generation for merged declarations Apr 16, 2026
@brijeshb42 brijeshb42 force-pushed the fix-proptypes-generation branch from 06ecde2 to 1801414 Compare April 16, 2026 05:53
…eclarations

The `getSymbolDocumentation` function was introduced in mui#47685 to handle
JSDoc merging across multiple TypeScript declarations. However, it
unconditionally joined all unique JSDoc comments when a symbol had
multiple declarations, which produced duplicated descriptions in the
generated propTypes for interface declaration merging and module
augmentation scenarios.

TypeScript treats JSDoc differently depending on how declarations
combine:

- Intersection types (type C = A & B): all constituent JSDoc are merged
- Interface extends (interface Z extends X, Y): first parent's JSDoc
wins
- Interface override (interface W extends X { prop }): the override's
JSDoc wins
- Declaration merging / module augmentation: last declaration's JSDoc
wins

The previous implementation treated all multi-declaration cases as
intersections, concatenating distinct comments. This caused issues in
downstream repos (e.g. mui-x) where module augmentation is used to
extend interface props — the original and augmented JSDoc would both
appear in the generated propTypes output.

The fix now uses `parentType.isIntersection()` to distinguish
intersection types (where merging is correct) from declaration merging
(where the last declaration should win), matching TypeScript's own
behavior.

Added test cases for all four JSDoc resolution scenarios:
- jsdoc-intersection: verifies both descriptions are merged
- jsdoc-interface-extends: verifies first parent's description wins
- jsdoc-interface-override: verifies override description wins
- declaration-merging: verifies last (augmented) description wins
@brijeshb42 brijeshb42 force-pushed the fix-proptypes-generation branch from 1801414 to 4b24028 Compare April 16, 2026 05:54
@brijeshb42 brijeshb42 requested review from a team and JCQuintas April 16, 2026 05:54
@code-infra-dashboard
Copy link
Copy Markdown

Bundle size

Bundle Parsed size Gzip size
@mui/material 0B(0.00%) 0B(0.00%)
@mui/lab 0B(0.00%) 0B(0.00%)
@mui/private-theming 0B(0.00%) 0B(0.00%)
@mui/system 0B(0.00%) 0B(0.00%)
@mui/utils 0B(0.00%) 0B(0.00%)

Details of bundle changes

Deploy preview

https://deploy-preview-48296--material-ui.netlify.app/


Check out the code infra dashboard for more information about this PR.


const decl = symbol.getDeclarations();
if (decl && decl.length > 0) {
// This behavior tries to replicate how TypeScript itself merges JSDoc comments
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this comment not valid anymore?

Comment on lines +13 to +17
/**
* Augmented description of the callback.
* @param {MouseEvent | React.MouseEvent} event The event source (augmented).
*/
onItemClick: PropTypes.func,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I suppose this is "somewhat correct"?

Like, the real ts implementation resolves to different overloads (because it is an interface with functions), for natives objects it still merges the docs.

I've added more examples to the ts playground

But since proptypes will likely only care for the most complete, I guess in this case it makes sense to pick last?

Copy link
Copy Markdown
Contributor Author

@brijeshb42 brijeshb42 Apr 16, 2026

Choose a reason for hiding this comment

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

Most complete will need further refinement. 1st definition could also technically be more complete. But in this case (and in the relevant example in Charts), there is an augmented type that is more complete that comes later in the definition. So I went with that way of just picking the last. Devs would have to make sure that later definitions are more complete.

Copy link
Copy Markdown
Contributor Author

@brijeshb42 brijeshb42 Apr 16, 2026

Choose a reason for hiding this comment

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

We can refine this further as need arises. But this change doesnt affect anything in core and in X only 3-4 files are affected.

@brijeshb42 brijeshb42 merged commit b5f653e into mui:master Apr 16, 2026
19 checks passed
@brijeshb42 brijeshb42 deleted the fix-proptypes-generation branch April 16, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: docs-infra Involves the docs-infra product (https://www.notion.so/mui-org/b9f676062eb94747b6768209f7751305).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants