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
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/mui-material/src/Accordion/Accordion.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ declare const Accordion: OverridableComponent<AccordionTypeMap>;
export type AccordionProps<
RootComponent extends React.ElementType = AccordionTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<AccordionTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<AccordionTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Accordion;
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ declare const AccordionSummary: ExtendButtonBase<AccordionSummaryTypeMap>;
export type AccordionSummaryProps<
RootComponent extends React.ElementType = AccordionSummaryTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<AccordionSummaryTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<AccordionSummaryTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default AccordionSummary;
4 changes: 3 additions & 1 deletion packages/mui-material/src/AppBar/AppBar.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ declare const AppBar: OverridableComponent<AppBarTypeMap>;
export type AppBarProps<
RootComponent extends React.ElementType = AppBarTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<AppBarTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<AppBarTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default AppBar;
4 changes: 3 additions & 1 deletion packages/mui-material/src/Avatar/Avatar.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ declare const Avatar: OverridableComponent<AvatarTypeMap>;
export type AvatarProps<
RootComponent extends React.ElementType = AvatarTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<AvatarTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<AvatarTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Avatar;
4 changes: 3 additions & 1 deletion packages/mui-material/src/Backdrop/Backdrop.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ declare const Backdrop: OverridableComponent<BackdropTypeMap>;
export type BackdropProps<
RootComponent extends React.ElementType = BackdropTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<BackdropTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<BackdropTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Backdrop;
4 changes: 3 additions & 1 deletion packages/mui-material/src/Badge/Badge.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ declare const Badge: OverridableComponent<BadgeTypeMap>;
export type BadgeProps<
RootComponent extends React.ElementType = BadgeTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<BadgeTypeMap<RootComponent, AdditionalProps>, RootComponent>;
> = OverrideProps<BadgeTypeMap<RootComponent, AdditionalProps>, RootComponent> & {
component?: React.ElementType;
};

export default Badge;
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ declare const BottomNavigation: OverridableComponent<BottomNavigationTypeMap>;
export type BottomNavigationProps<
RootComponent extends React.ElementType = BottomNavigationTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<BottomNavigationTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<BottomNavigationTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default BottomNavigation;
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ declare const BottomNavigationAction: ExtendButtonBase<
export type BottomNavigationActionProps<
RootComponent extends React.ElementType = ButtonBaseTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<BottomNavigationActionTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<BottomNavigationActionTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default BottomNavigationAction;
4 changes: 3 additions & 1 deletion packages/mui-material/src/Breadcrumbs/Breadcrumbs.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ declare const Breadcrumbs: OverridableComponent<BreadcrumbsTypeMap>;
export type BreadcrumbsProps<
RootComponent extends React.ElementType = BreadcrumbsTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<BreadcrumbsTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<BreadcrumbsTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Breadcrumbs;
4 changes: 3 additions & 1 deletion packages/mui-material/src/Button/Button.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ declare const Button: ExtendButtonBase<ButtonTypeMap>;
export type ButtonProps<
RootComponent extends React.ElementType = ButtonTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<ButtonTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<ButtonTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Button;
41 changes: 41 additions & 0 deletions packages/mui-material/src/Button/Button.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import Button, { ButtonProps } from '@mui/material/Button';
import MaterialUiLink, { LinkProps as MaterialUiLinkProps } from '@mui/material/Link';
import { Link as ReactRouterLink, LinkProps } from 'react-router-dom';
import { expectType } from '@mui/types';

Expand All @@ -9,10 +10,47 @@ const TestOverride = React.forwardRef<HTMLDivElement, { x?: number }>((props, re
<div ref={ref} />
));

type CustomLinkProps = MaterialUiLinkProps<typeof ReactRouterLink, LinkProps>;
const CustomLink: React.FC<React.PropsWithChildren<CustomLinkProps>> = ({ children, ...props }) => {
return (
<MaterialUiLink component={ReactRouterLink} {...props}>
{children}
</MaterialUiLink>
);
};

function FakeIcon() {
return <div>Icon</div>;
}

const props1: ButtonProps<'div'> = {
component: 'div',
onChange: (event) => {
expectType<React.FormEvent<HTMLDivElement>, typeof event>(event);
},
};

const props2: ButtonProps = {
onChange: (event) => {
expectType<React.FormEvent<HTMLButtonElement>, typeof event>(event);
},
};

const props3: ButtonProps<typeof TestOverride> = {
component: TestOverride,
x: 2,
};

const props4: ButtonProps<typeof TestOverride> = {
component: TestOverride,
// @ts-expect-error TestOverride does not accept incorrectProp
incorrectProp: 3,
};

const props5: ButtonProps<typeof TestOverride> = {
component: TestOverride,
};

const buttonTest = () => (
<div>
<Button>I am a button!</Button>
Expand All @@ -36,6 +74,9 @@ const buttonTest = () => (
<Button component={ReactRouterLink} to="/open-collective">
Link
</Button>
<Button component={CustomLink} to="/some-route">
Link
</Button>
<Button href="/open-collective">Link</Button>
{/* By default the underlying component is a button element */}
<Button
Expand Down
4 changes: 3 additions & 1 deletion packages/mui-material/src/ButtonBase/ButtonBase.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ declare const ButtonBase: ExtendButtonBase<ButtonBaseTypeMap>;
export type ButtonBaseProps<
RootComponent extends React.ElementType = ButtonBaseTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<ButtonBaseTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<ButtonBaseTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export interface ButtonBaseActions {
focusVisible(): void;
Expand Down
4 changes: 3 additions & 1 deletion packages/mui-material/src/ButtonGroup/ButtonGroup.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ declare const ButtonGroup: OverridableComponent<ButtonGroupTypeMap>;
export type ButtonGroupProps<
RootComponent extends React.ElementType = ButtonGroupTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<ButtonGroupTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<ButtonGroupTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default ButtonGroup;
8 changes: 5 additions & 3 deletions packages/mui-material/src/Card/Card.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { SxProps } from '@mui/system';
import { DistributiveOmit } from '@mui/types';
import { OverridableComponent, OverrideProps } from '@mui/material/OverridableComponent';
import { Theme } from '..';
import { PaperProps } from '../Paper';
import { PaperOwnProps } from '../Paper';
import { CardClasses } from './cardClasses';

// TODO: v6 remove this interface, it is not used
Expand All @@ -14,7 +14,7 @@ export interface CardTypeMap<
DefaultComponent extends React.ElementType = 'div',
> {
props: AdditionalProps &
DistributiveOmit<PaperProps, 'classes'> & {
DistributiveOmit<PaperOwnProps, 'classes'> & {
/**
* Override or extend the styles applied to the component.
*/
Expand Down Expand Up @@ -49,6 +49,8 @@ declare const Card: OverridableComponent<CardTypeMap>;
export type CardProps<
RootComponent extends React.ElementType = CardTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<CardTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<CardTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Card;
34 changes: 34 additions & 0 deletions packages/mui-material/src/Card/Card.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as React from 'react';
import Card from '@mui/material/Card';
import { expectType } from '@mui/types';

const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> =
function CustomComponent() {
return <div />;
};

function CardTest() {
return (
<div>
<Card />
<Card elevation={4} />
<Card
onClick={(event) => {
expectType<React.MouseEvent<HTMLDivElement, MouseEvent>, typeof event>(event);
}}
/>
<Card
component="a"
href="test"
onClick={(event) => {
expectType<React.MouseEvent<HTMLAnchorElement, MouseEvent>, typeof event>(event);
}}
/>
<Card component="a" href="test" />

<Card component={CustomComponent} stringProp="test" numberProp={0} />
{/* @ts-expect-error missing stringProp and numberProp */}
<Card component={CustomComponent} />
</div>
);
}
4 changes: 3 additions & 1 deletion packages/mui-material/src/CardActionArea/CardActionArea.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ declare const CardActionArea: ExtendButtonBase<
export type CardActionAreaProps<
RootComponent extends React.ElementType = ButtonBaseTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<CardActionAreaTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<CardActionAreaTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default CardActionArea;
4 changes: 3 additions & 1 deletion packages/mui-material/src/CardContent/CardContent.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ declare const CardContent: OverridableComponent<CardContentTypeMap>;
export type CardContentProps<
RootComponent extends React.ElementType = CardContentTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<CardContentTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<CardContentTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default CardContent;
18 changes: 9 additions & 9 deletions packages/mui-material/src/CardHeader/CardHeader.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,38 +12,38 @@ interface ComponentProp {
component?: React.ElementType;
}

<CardHeader component={CustomComponent} stringProp="s" numberProp={2} />;

function createElementBasePropMixedTest() {
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader);
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
component: 'div',
});
// ExpectError: type system should be demanding the required props of "CustomComponent"
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
// @ts-expect-error required props are missing
React.createElement<CardHeaderProps<typeof CustomComponent, ComponentProp>>(CardHeader, {
component: CustomComponent,
});
// @ts-expect-error
React.createElement<CardHeaderProps<DefaultComponent, ComponentProp>>(CardHeader, {
// This test shouldn't fail but does; stringProp & numberProp are required props of CustomComponent
React.createElement<CardHeaderProps<typeof CustomComponent, ComponentProp>>(CardHeader, {
component: CustomComponent,
stringProp: '',
numberProp: 0,
});
React.createElement<CardHeaderProps>(CardHeader, {
disableTypography: true,
});
// @ts-expect-error
// @ts-expect-error CardHeader does not accept unknownProp
React.createElement<CardHeaderProps<DefaultComponent, {}, React.ElementType>>(CardHeader, {
unknownProp: 'shouldNotWork',
});
// @ts-expect-error
// @ts-expect-error disableTypography does not accept strings
React.createElement<CardHeaderProps>(CardHeader, {
disableTypography: 'hello',
});
// @ts-expect-error
// @ts-expect-error disableTypography does not accept numbers
React.createElement<CardHeaderProps>(CardHeader, {
disableTypography: 1,
});
// @ts-expect-error
// @ts-expect-error `component` is not a valid element
React.createElement<CardHeaderProps<any, ComponentProp>>(CardHeader, {
component: 'incorrectElement',
});
Expand Down
4 changes: 3 additions & 1 deletion packages/mui-material/src/CardMedia/CardMedia.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ declare const CardMedia: OverridableComponent<CardMediaTypeMap<{}, 'div'>>;
export type CardMediaProps<
RootComponent extends React.ElementType = 'div',
AdditionalProps = {},
> = OverrideProps<CardMediaTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<CardMediaTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default CardMedia;
4 changes: 3 additions & 1 deletion packages/mui-material/src/Chip/Chip.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ declare const Chip: OverridableComponent<ChipTypeMap>;
export type ChipProps<
RootComponent extends React.ElementType = ChipTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<ChipTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<ChipTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Chip;
4 changes: 3 additions & 1 deletion packages/mui-material/src/Container/Container.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ declare const Container: OverridableComponent<ContainerTypeMap>;
export type ContainerProps<
RootComponent extends React.ElementType = ContainerTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<ContainerTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<ContainerTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default Container;
2 changes: 1 addition & 1 deletion packages/mui-material/src/Dialog/Dialog.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export interface DialogProps extends StandardProps<ModalProps, 'children'> {
* Props applied to the [`Paper`](/material-ui/api/paper/) element.
* @default {}
*/
PaperProps?: Partial<PaperProps>;
PaperProps?: Partial<PaperProps<React.ElementType>>;
/**
* Determine the container for scrolling the dialog.
* @default 'paper'
Expand Down
19 changes: 16 additions & 3 deletions packages/mui-material/src/Dialog/Dialog.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import * as React from 'react';
import { Dialog } from '@mui/material';
import Dialog from '@mui/material/Dialog';
import { PaperProps } from '@mui/material/Paper';
import { expectType } from '@mui/types';

function optionalChildrenTest() {
<Dialog open />;
const paperProps: PaperProps<'span'> = {
component: 'span',
onClick: (event) => {
expectType<React.MouseEvent<HTMLSpanElement, MouseEvent>, typeof event>(event);
},
};
function Test() {
return (
<React.Fragment>
<Dialog open />;
<Dialog open PaperProps={paperProps} />;
</React.Fragment>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ declare const DialogContentText: OverridableComponent<DialogContentTextTypeMap>;
export type DialogContentTextProps<
RootComponent extends React.ElementType = DialogContentTextTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<DialogContentTextTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<DialogContentTextTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default DialogContentText;
4 changes: 3 additions & 1 deletion packages/mui-material/src/DialogTitle/DialogTitle.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ declare const DialogTitle: OverridableComponent<DialogTitleTypeMap>;
export type DialogTitleProps<
RootComponent extends React.ElementType = DialogTitleTypeMap['defaultComponent'],
AdditionalProps = { component?: React.ElementType },
> = OverrideProps<DialogTitleTypeMap<AdditionalProps, RootComponent>, RootComponent>;
> = OverrideProps<DialogTitleTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType;
};

export default DialogTitle;
Loading
Loading