Skip to content

Commit 1b9c8ab

Browse files
authored
[core] Adds component prop to OverrideProps type (#35924)
1 parent db2968e commit 1b9c8ab

29 files changed

+540
-129
lines changed

docs/data/material/guides/routing/LinkRouterWithTheme.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { StaticRouter } from 'react-router-dom/server';
88
import { ThemeProvider, createTheme } from '@mui/material/styles';
99
import Button from '@mui/material/Button';
1010
import Stack from '@mui/material/Stack';
11-
import Link, { LinkProps } from '@mui/material/Link';
11+
import Link from '@mui/material/Link';
1212

1313
const LinkBehavior = React.forwardRef<
1414
HTMLAnchorElement,
@@ -33,7 +33,7 @@ const theme = createTheme({
3333
MuiLink: {
3434
defaultProps: {
3535
component: LinkBehavior,
36-
} as LinkProps,
36+
},
3737
},
3838
MuiButtonBase: {
3939
defaultProps: {

docs/data/material/guides/routing/routing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const theme = createTheme({
4141
MuiLink: {
4242
defaultProps: {
4343
component: LinkBehavior,
44-
} as LinkProps,
44+
},
4545
},
4646
MuiButtonBase: {
4747
defaultProps: {

docs/src/modules/components/Link.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export type LinkProps = {
6464
linkAs?: NextLinkProps['as']; // Useful when the as prop is shallow by styled().
6565
noLinkStyle?: boolean;
6666
} & Omit<NextLinkComposedProps, 'to' | 'linkAs' | 'href'> &
67-
Omit<MuiLinkProps, 'href'>;
67+
Omit<MuiLinkProps, 'href' | 'component'>;
6868

6969
// A styled version of the Next.js Link component:
7070
// https://nextjs.org/docs/api-reference/next/link

packages/mui-material/src/Button/Button.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ Button.propTypes /* remove-proptypes */ = {
396396
* The component used for the root node.
397397
* Either a string to use a HTML element or a component.
398398
*/
399-
component: PropTypes.elementType,
399+
component: PropTypes /* @typescript-to-proptypes-ignore */.elementType,
400400
/**
401401
* If `true`, the component is disabled.
402402
* @default false

packages/mui-material/src/Button/Button.spec.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,39 @@ function FakeIcon() {
1313
return <div>Icon</div>;
1414
}
1515

16+
const props1: ButtonProps<'div'> = {
17+
component: 'div',
18+
onChange: (event) => {
19+
expectType<React.FormEvent<HTMLDivElement>, typeof event>(event);
20+
},
21+
};
22+
23+
const props2: ButtonProps = {
24+
onChange: (event) => {
25+
expectType<React.FormEvent<HTMLButtonElement>, typeof event>(event);
26+
},
27+
};
28+
29+
const props3: ButtonProps<'span'> = {
30+
// @ts-expect-error
31+
component: 'div',
32+
};
33+
34+
const props4: ButtonProps<typeof TestOverride> = {
35+
component: TestOverride,
36+
x: 2,
37+
};
38+
39+
const props5: ButtonProps<typeof TestOverride> = {
40+
component: TestOverride,
41+
// @ts-expect-error
42+
inCorrectProp: 3,
43+
};
44+
45+
const props6: ButtonProps<typeof TestOverride> = {
46+
component: TestOverride,
47+
};
48+
1649
const buttonTest = () => (
1750
<div>
1851
<Button>I am a button!</Button>

packages/mui-material/src/Card/Card.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ import { SxProps } from '@mui/system';
33
import { DistributiveOmit } from '@mui/types';
44
import { OverridableComponent, OverrideProps } from '@mui/material/OverridableComponent';
55
import { Theme } from '..';
6-
import { PaperProps } from '../Paper';
6+
import { PaperOwnProps } from '../Paper';
77
import { CardClasses } from './cardClasses';
88

99
// TODO: v6 remove this interface, it is not used
1010
export interface CardPropsColorOverrides {}
1111

1212
export interface CardTypeMap<P = {}, D extends React.ElementType = 'div'> {
1313
props: P &
14-
DistributiveOmit<PaperProps, 'classes'> & {
14+
DistributiveOmit<PaperOwnProps, 'classes'> & {
1515
/**
1616
* Override or extend the styles applied to the component.
1717
*/
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as React from 'react';
2+
import Card from '@mui/material/Card';
3+
import { expectType } from '@mui/types';
4+
5+
const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
6+
function CustomComponent() {
7+
return <div />;
8+
};
9+
10+
function CardTest() {
11+
return (
12+
<div>
13+
<Card />
14+
<Card elevation={4} />
15+
<Card
16+
onClick={(event) => {
17+
expectType<React.MouseEvent<HTMLDivElement, MouseEvent>, typeof event>(event);
18+
}}
19+
/>
20+
<Card
21+
component="a"
22+
href="test"
23+
onClick={(event) => {
24+
expectType<React.MouseEvent<HTMLAnchorElement, MouseEvent>, typeof event>(event);
25+
}}
26+
/>
27+
28+
<Card component={CustomComponent} stringProp="test" numberProp={0} />
29+
{/* @ts-expect-error missing stringProp and numberProp */}
30+
<Card component={CustomComponent} />
31+
</div>
32+
);
33+
}

packages/mui-material/src/CardHeader/CardHeader.spec.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,23 @@ interface ComponentProp {
1212
component?: React.ElementType;
1313
}
1414

15+
<CardHeader component={CustomComponent} stringProp="s" numberProp={2} />;
16+
1517
function createElementBasePropMixedTest() {
1618
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader);
1719
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
1820
component: 'div',
1921
});
2022
// ExpectError: type system should be demanding the required props of "CustomComponent"
21-
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
23+
// @ts-expect-error
24+
React.createElement<CardHeaderProps<typeof CustomComponent>>(CardHeader, {
2225
component: CustomComponent,
26+
stringProp: '2',
27+
numberProp: 3,
28+
incorrectProp: 3,
2329
});
24-
// @ts-expect-error
25-
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
26-
// This test shouldn't fail but does; stringProp & numberProp are required props of CustomComponent
30+
31+
React.createElement<CardHeaderProps<typeof CustomComponent>>(CardHeader, {
2732
component: CustomComponent,
2833
stringProp: '',
2934
numberProp: 0,

packages/mui-material/src/Dialog/Dialog.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export interface DialogProps extends StandardProps<ModalProps, 'children'> {
7272
* Props applied to the [`Paper`](/material-ui/api/paper/) element.
7373
* @default {}
7474
*/
75-
PaperProps?: Partial<PaperProps>;
75+
PaperProps?: Partial<PaperProps<React.ElementType>>;
7676
/**
7777
* Determine the container for scrolling the dialog.
7878
* @default 'paper'
Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
import * as React from 'react';
2-
import { Dialog } from '@mui/material';
2+
import Dialog from '@mui/material/Dialog';
3+
import { PaperProps } from '@mui/material/Paper';
4+
import { expectType } from '@mui/types';
35

4-
function optionalChildrenTest() {
5-
<Dialog open />;
6+
const paperProps: PaperProps<'span'> = {
7+
component: 'span',
8+
onClick: (event) => {
9+
expectType<React.MouseEvent<HTMLSpanElement, MouseEvent>, typeof event>(event);
10+
},
11+
};
12+
function Test() {
13+
return (
14+
<React.Fragment>
15+
<Dialog open />;
16+
<Dialog open PaperProps={paperProps} />;
17+
</React.Fragment>
18+
);
619
}

packages/mui-material/src/Drawer/Drawer.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export interface DrawerProps extends StandardProps<ModalProps, 'open' | 'childre
4646
* Props applied to the [`Paper`](/material-ui/api/paper/) element.
4747
* @default {}
4848
*/
49-
PaperProps?: Partial<PaperProps>;
49+
PaperProps?: Partial<PaperProps<React.ElementType>>;
5050
/**
5151
* Props applied to the [`Slide`](/material-ui/api/slide/) element.
5252
*/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import Drawer from '@mui/material/Drawer';
3+
import { PaperProps } from '@mui/material/Paper';
4+
import { expectType } from '@mui/types';
5+
6+
const paperProps: PaperProps<'span'> = {
7+
component: 'span',
8+
onClick: (event) => {
9+
expectType<React.MouseEvent<HTMLSpanElement, MouseEvent>, typeof event>(event);
10+
},
11+
};
12+
function Test() {
13+
return (
14+
<React.Fragment>
15+
<Drawer open />;
16+
<Drawer open PaperProps={paperProps} />;
17+
</React.Fragment>
18+
);
19+
}

packages/mui-material/src/Fab/Fab.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ Fab.propTypes /* remove-proptypes */ = {
221221
* The component used for the root node.
222222
* Either a string to use a HTML element or a component.
223223
*/
224-
component: PropTypes.elementType,
224+
component: PropTypes /* @typescript-to-proptypes-ignore */.elementType,
225225
/**
226226
* If `true`, the component is disabled.
227227
* @default false
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import * as React from 'react';
2+
import FormHelperText, { FormHelperTextProps } from '@mui/material/FormHelperText';
3+
import { expectType } from '@mui/types';
4+
5+
const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
6+
function CustomComponent() {
7+
return <div />;
8+
};
9+
10+
const props: FormHelperTextProps<'div'> = {
11+
component: 'div',
12+
onChange: (event) => {
13+
expectType<React.FormEvent<HTMLDivElement>, typeof event>(event);
14+
},
15+
};
16+
17+
const props2: FormHelperTextProps = {
18+
onChange: (event) => {
19+
expectType<React.FormEvent<HTMLParagraphElement>, typeof event>(event);
20+
},
21+
};
22+
23+
const props3: FormHelperTextProps<'span'> = {
24+
// @ts-expect-error
25+
component: 'div',
26+
};
27+
28+
const props4: FormHelperTextProps<typeof CustomComponent> = {
29+
component: CustomComponent,
30+
stringProp: '2',
31+
numberProp: 2,
32+
};
33+
34+
const props5: FormHelperTextProps<typeof CustomComponent> = {
35+
component: CustomComponent,
36+
stringProp: '2',
37+
numberProp: 2,
38+
// @ts-expect-error
39+
inCorrectProp: 3,
40+
};
41+
42+
// @ts-expect-error
43+
const props6: FormHelperTextProps<typeof CustomComponent> = {
44+
component: CustomComponent,
45+
};
46+
47+
const TestComponent = () => {
48+
return (
49+
<React.Fragment>
50+
<FormHelperText />
51+
<FormHelperText component={'a'} href="/test" />
52+
53+
<FormHelperText component={CustomComponent} stringProp="s" numberProp={1} />
54+
{
55+
// @ts-expect-error
56+
<FormHelperText component={CustomComponent} />
57+
}
58+
<FormHelperText
59+
component="span"
60+
onChange={(event) => {
61+
expectType<React.FormEvent<HTMLSpanElement>, typeof event>(event);
62+
}}
63+
/>
64+
</React.Fragment>
65+
);
66+
};
Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,68 @@
11
import * as React from 'react';
22
import Paper from '@mui/material/Paper';
3-
import Grid from '@mui/material/Grid';
3+
import Grid, { GridProps } from '@mui/material/Grid';
4+
import { expectType } from '@mui/types';
5+
6+
const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
7+
function CustomComponent() {
8+
return <div />;
9+
};
10+
11+
const props: GridProps<'span'> = {
12+
component: 'span',
13+
onChange: (event) => {
14+
expectType<React.FormEvent<HTMLSpanElement>, typeof event>(event);
15+
},
16+
};
17+
18+
const props2: GridProps = {
19+
onChange: (event) => {
20+
expectType<React.FormEvent<HTMLDivElement>, typeof event>(event);
21+
},
22+
};
23+
24+
const props3: GridProps<'span'> = {
25+
// @ts-expect-error
26+
component: 'div',
27+
};
28+
29+
const props4: GridProps<typeof CustomComponent> = {
30+
component: CustomComponent,
31+
stringProp: '2',
32+
numberProp: 2,
33+
};
34+
35+
const props5: GridProps<typeof CustomComponent> = {
36+
component: CustomComponent,
37+
stringProp: '2',
38+
numberProp: 2,
39+
// @ts-expect-error
40+
inCorrectProp: 3,
41+
};
42+
43+
// @ts-expect-error
44+
const props6: GridProps<typeof CustomComponent> = {
45+
component: CustomComponent,
46+
};
447

548
function ResponsiveTest() {
6-
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square />;
49+
return (
50+
<React.Fragment>
51+
<Grid item xs={12} sm={8} md={5} component={Paper} elevation={6} square />
52+
<Grid item component={'a'} href="/test" />
53+
54+
<Grid item component={CustomComponent} stringProp="s" numberProp={1} />
55+
{
56+
// @ts-expect-error
57+
<Grid item component={CustomComponent} />
58+
}
59+
<Grid
60+
item
61+
component="span"
62+
onChange={(event) => {
63+
expectType<React.FormEvent<HTMLSpanElement>, typeof event>(event);
64+
}}
65+
/>
66+
</React.Fragment>
67+
);
768
}

0 commit comments

Comments
 (0)