diff --git a/packages/material-ui/src/CardHeader/CardHeader.d.ts b/packages/material-ui/src/CardHeader/CardHeader.d.ts
index 0a3c3f564e2f8b..61873bb281abc5 100644
--- a/packages/material-ui/src/CardHeader/CardHeader.d.ts
+++ b/packages/material-ui/src/CardHeader/CardHeader.d.ts
@@ -2,17 +2,28 @@ import * as React from 'react';
import { TypographyProps } from '../Typography';
import { OverridableComponent, OverrideProps } from '../OverridableComponent';
-export interface CardHeaderTypeMap
{
- props: P & {
+export interface CardHeaderTypeMap<
+ Props = {},
+ DefaultComponent extends React.ElementType = 'div',
+ TitleTypographyComponent extends React.ElementType = 'span',
+ SubheaderTypographyComponent extends React.ElementType = 'span'
+> {
+ props: Props & {
action?: React.ReactNode;
avatar?: React.ReactNode;
disableTypography?: boolean;
subheader?: React.ReactNode;
- subheaderTypographyProps?: Partial;
+ subheaderTypographyProps?: TypographyProps<
+ SubheaderTypographyComponent,
+ { component?: SubheaderTypographyComponent }
+ >;
title?: React.ReactNode;
- titleTypographyProps?: Partial;
+ titleTypographyProps?: TypographyProps<
+ TitleTypographyComponent,
+ { component?: TitleTypographyComponent }
+ >;
};
- defaultComponent: D;
+ defaultComponent: DefaultComponent;
classKey: CardHeaderClassKey;
}
/**
@@ -25,13 +36,51 @@ export interface CardHeaderTypeMap
*
* - [CardHeader API](https://material-ui.com/api/card-header/)
*/
-declare const CardHeader: OverridableComponent;
+declare const CardHeader: OverridableCardHeader;
+
+export interface OverridableCardHeader extends OverridableComponent {
+ <
+ DefaultComponent extends React.ElementType = CardHeaderTypeMap['defaultComponent'],
+ Props = {},
+ TitleTypographyComponent extends React.ElementType = 'span',
+ SubheaderTypographyComponent extends React.ElementType = 'span'
+ >(
+ props: CardHeaderPropsWithComponent<
+ DefaultComponent,
+ Props,
+ TitleTypographyComponent,
+ SubheaderTypographyComponent
+ >,
+ ): JSX.Element;
+}
export type CardHeaderClassKey = 'root' | 'avatar' | 'action' | 'content' | 'title' | 'subheader';
export type CardHeaderProps<
- D extends React.ElementType = CardHeaderTypeMap['defaultComponent'],
- P = {}
-> = OverrideProps, D>;
+ DefaultComponent extends React.ElementType = CardHeaderTypeMap['defaultComponent'],
+ Props = {},
+ TitleTypographyComponent extends React.ElementType = 'span',
+ SubheaderTypographyComponent extends React.ElementType = 'span'
+> = OverrideProps<
+ CardHeaderTypeMap<
+ Props,
+ DefaultComponent,
+ TitleTypographyComponent,
+ SubheaderTypographyComponent
+ >,
+ DefaultComponent
+>;
+
+export type CardHeaderPropsWithComponent<
+ DefaultComponent extends React.ElementType = CardHeaderTypeMap['defaultComponent'],
+ Props = {},
+ TitleTypographyComponent extends React.ElementType = 'span',
+ SubheaderTypographyComponent extends React.ElementType = 'span'
+> = { component?: DefaultComponent } & CardHeaderProps<
+ DefaultComponent,
+ Props,
+ TitleTypographyComponent,
+ SubheaderTypographyComponent
+>;
export default CardHeader;
diff --git a/packages/material-ui/src/CardHeader/CardHeader.spec.tsx b/packages/material-ui/src/CardHeader/CardHeader.spec.tsx
new file mode 100644
index 00000000000000..98e49411350ecb
--- /dev/null
+++ b/packages/material-ui/src/CardHeader/CardHeader.spec.tsx
@@ -0,0 +1,299 @@
+import * as React from 'react';
+import CardHeader, { CardHeaderProps, CardHeaderTypeMap } from '@material-ui/core/CardHeader';
+
+const CustomComponent: React.FC<{ stringProp: string; numberProp: number }> = () => ;
+
+type DefaultComponent = CardHeaderTypeMap['defaultComponent'];
+
+interface ComponentProp {
+ component?: React.ElementType;
+}
+
+function createElementBasePropMixedTest() {
+ React.createElement>(CardHeader);
+ React.createElement>(CardHeader, {
+ component: 'div',
+ });
+ // ExpectError: type system should be demanding the required props of "CustomComponent"
+ React.createElement>(CardHeader, {
+ component: CustomComponent,
+ });
+ // $ExpectError
+ React.createElement>(CardHeader, {
+ // This test shouldn't fail but does; stringProp & numberProp are required props of CustomComponent
+ component: CustomComponent,
+ stringProp: '',
+ numberProp: 0,
+ });
+ React.createElement(CardHeader, {
+ disableTypography: true,
+ });
+ // $ExpectError
+ React.createElement>(CardHeader, {
+ unknownProp: 'shouldNotWork',
+ });
+ // $ExpectError
+ React.createElement(CardHeader, {
+ disableTypography: 'hello',
+ });
+ // $ExpectError
+ React.createElement(CardHeader, {
+ disableTypography: 1,
+ });
+ // $ExpectError
+ React.createElement>(CardHeader, {
+ component: 'incorrectElement',
+ });
+}
+
+function createElementTypographyTest() {
+ React.createElement(CardHeader, {
+ titleTypographyProps: {
+ align: 'center',
+ },
+ });
+ // $ExpectError
+ React.createElement(CardHeader, {
+ titleTypographyProps: {
+ align: 'incorrectAlign',
+ },
+ });
+ React.createElement(CardHeader, {
+ titleTypographyProps: {
+ variant: 'body1',
+ },
+ });
+ // $ExpectError
+ React.createElement(CardHeader, {
+ titleTypographyProps: {
+ variant: 123,
+ },
+ });
+ React.createElement>(CardHeader, {
+ titleTypographyProps: {
+ component: 'div',
+ },
+ });
+ // ExpectError: This is expected to err; the type system should catch required props from "CustomComponent".
+ React.createElement>(CardHeader, {
+ titleTypographyProps: {
+ component: CustomComponent,
+ },
+ });
+ React.createElement>(CardHeader, {
+ titleTypographyProps: {
+ component: CustomComponent,
+ stringProp: '',
+ numberProp: 0,
+ },
+ });
+ // ExpectError: This is expected to err; the type system should catch the props type mismatch
+ // from "CustomComponent" props.
+ React.createElement>(CardHeader, {
+ titleTypographyProps: {
+ component: CustomComponent,
+ stringProp: 0,
+ numberProp: '',
+ },
+ });
+ // ExpectError: This is expected to err; the type system is welcoming unknown props.
+ React.createElement>(CardHeader, {
+ titleTypographyProps: {
+ unknownProp: 'shouldNotWork',
+ },
+ });
+ // $ExpectError
+ React.createElement>(CardHeader, {
+ titleTypographyProps: {
+ component: 'incorrectComponent',
+ },
+ });
+ // $ExpectError
+ React.createElement(CardHeader, {
+ titleTypographyProps: true,
+ });
+}
+
+function componentPropTest() {
+ ;
+ ;
+ // $ExpectError
+ ;
+ // $ExpectError
+ ;
+}
+
+function mixedCardHeaderComponentAndTypographyTest() {
+ ;
+ ;
+ ;
+ ;
+ // $ExpectError
+ ;
+ // $ExpectError
+ ;
+ ;
+ // $ExpectError
+ ;
+ ;
+}
+
+function titleTypographyPropsTest() {
+ // $ExpectError
+ ;
+ ;
+ ;
+ ;
+ ;
+ ;
+ // $ExpectError
+ ;
+ // $ExpectError
+ ;
+ ;
+}
+
+function subheaderTypographyPropsTest() {
+ ;
+ ;
+ ;
+ ;
+ ;
+ ;
+ // $ExpectError
+ ;
+ // $ExpectError
+ ;
+}
+
+function mixedTypographyPropsTest() {
+ ;
+ ;
+ // $ExpectError
+ ;
+ ;
+ // $ExpectError
+ ;
+ ;
+ ;
+}