Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[typescript] Add component field to *Props types #38084

Merged
merged 19 commits into from
Jul 27, 2023

Conversation

michaldudak
Copy link
Member

@michaldudak michaldudak commented Jul 21, 2023

This is a different implementation of the fix proposed in #35924, which was reverted in #38150, as it caused some problems.

Instead of adding the { component?: D } to OverrideProps, { component?: React.ElementType } is added to each individual *Props type. This solution doesn't cause problems as *Props aren't used where a component is instantiated (they are not a part of OverridableComponent definition), unlike OverrideProps. OverridableComponent already has a definition for the component prop and it's used to determine if a component uses its default root, or a customized one. Adding yet another definition of component to it turned out to cause issues.

Tests written in #35924 were copied to this PR. Also, tests verifying the regressions reported after #35924 was released were also added to the PR.

@michaldudak michaldudak added core Infrastructure work going on behind the scenes typescript labels Jul 21, 2023
@mui-bot
Copy link

mui-bot commented Jul 21, 2023

Netlify deploy preview

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

Bundle size report

No bundle size changes (Toolpad)
No bundle size changes

Generated by 🚫 dangerJS against 38e2dce

@@ -18,6 +18,6 @@ declare const Box: OverridableComponent<BoxTypeMap<{}, 'div', MaterialTheme>>;
export type BoxProps<
D extends React.ElementType = BoxTypeMap['defaultComponent'],
P = {},
> = OverrideProps<BoxTypeMap<P, D, MaterialTheme>, D>;
> = OverrideProps<BoxTypeMap<P, D, MaterialTheme>, D> & { component?: D };
Copy link
Contributor

Choose a reason for hiding this comment

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

@michaldudak after adding {component?:D} here - test from Stack.spec.tsx file is failing. here is the error from CI

Copy link
Member Author

Choose a reason for hiding this comment

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

Box already has the component defined in its TypeMap (packages\mui-system\src\Box\Box.d.ts), so it's not necessary to add it here.

Copy link
Contributor

@sai6855 sai6855 Jul 24, 2023

Choose a reason for hiding this comment

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

okay fair but when Box is replaced with Button - issue still persists. here is the codesandbox link : https://codesandbox.io/s/exciting-cloud-r4qvcm?file=/Demo.tsx. maybe underlying issue is different

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, right. In this case, when we don't provide a type parameter to the ButtonProps, it defaults to button, and make the whole type too strict to be passed to the Stack's component.
Defining the *Props with & { component?: React.ElementType } instead would help here, but it would allow writing <Button<'span'> component='div' />. I think we can have such a compromise.

Copy link
Member Author

Choose a reason for hiding this comment

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

I just committed this change, let's see how the CI will react.

Copy link
Contributor

@sai6855 sai6855 Jul 24, 2023

Choose a reason for hiding this comment

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

CI is green, shall I go ahead and add tests?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes please!

@michaldudak michaldudak marked this pull request as ready for review July 25, 2023 07:15
@michaldudak michaldudak requested a review from a team July 25, 2023 07:15
Copy link
Member

@mnajdova mnajdova left a comment

Choose a reason for hiding this comment

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

Can you please summarize the changes and why this change fixes the issues? Also, can you link the issue in the PR description? Thanks!

<Card
component="a"
href="test"
onClick={(event) => {
Copy link
Member

Choose a reason for hiding this comment

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

Why was this assertion removed?

Copy link
Contributor

Choose a reason for hiding this comment

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

@michaldudak after adding { component?: React.ElementType } to components, are types of event handlers expected to be inherited from component?

for example in below code - is type of event expected to be React.MouseEvent<HTMLDivElement, MouseEvent> or React.MouseEvent<HTMLAnchorElement, MouseEvent>. Right now event type is React.MouseEvent<HTMLDivElement, MouseEvent>

<Card
component='a'
        onClick={(event) => {
         
        }}
      />

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes - the *Props types are not used when you instantiate a component (OverridableComponent does not use *Props), so there should be no changes in this matter.
In case of the Card, this isn't true, though - its TypeMap uses PaperProps, which likely causes this problem.

Copy link
Member Author

Choose a reason for hiding this comment

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

@sai6855 I'm working on a fix for this.

React.createElement<CardHeaderProps<typeof CustomComponent>>(CardHeader, {
// @ts-expect-error
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
// This test shouldn't fail but does; stringProp & numberProp are required props of CustomComponent
Copy link
Member

Choose a reason for hiding this comment

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

Why does this fail?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's been like this even before #35924 - this is just restoring the original behavior.
As for why it's like this in the first place - I'm investigating it.

Copy link
Member Author

Choose a reason for hiding this comment

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

It looks like the test is incorrect: the type parameter was DefaultComponent while the component prop was set to something else. It is expected to fail.

@michaldudak michaldudak changed the title [core] Revert OverrideProps changes [core] Fix problems introduced by adding component to OverrideProps Jul 25, 2023
@michaldudak michaldudak added the package: material-ui Specific to @mui/material label Jul 25, 2023
@michaldudak michaldudak changed the title [core] Fix problems introduced by adding component to OverrideProps [typescript] Add component field to *Props types Jul 25, 2023
@michaldudak
Copy link
Member Author

@mnajdova, I addressed your remarks.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Jul 26, 2023
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Jul 26, 2023
Copy link
Member

@mnajdova mnajdova left a comment

Choose a reason for hiding this comment

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

Tests look great, before merging please add descriptions next to each // @ts-expect-error

@michaldudak michaldudak merged commit bca4565 into mui:master Jul 27, 2023
18 checks passed
@michaldudak michaldudak deleted the revert-overrideprops branch July 27, 2023 09:52
@michaldudak
Copy link
Member Author

@sai6855 Thanks for your help with this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core Infrastructure work going on behind the scenes package: material-ui Specific to @mui/material typescript
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants