Sitelet https://github.com/mui/material-ui/commit/dc1e49388022a0e332ed5fb8fd4be834a94ebb26
Skip to content

Commit dc1e493

Browse files
authored
[code-infra] Enable undefined addition to optional properties (#47815)
1 parent 02f315d commit dc1e493

245 files changed

Lines changed: 3583 additions & 2876 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎eslint.config.mjs‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,21 @@ export default defineConfig(
220220
},
221221
},
222222
{
223-
files: [`packages/*/src/*/*${EXTENSION_TS}`],
223+
files: [`packages/*/src/**/*${EXTENSION_TS}`, `packages/*/src/**/*${EXTENSION_DTS}`],
224+
ignores: [
225+
'**/*.spec.*',
226+
'**/*.test.*',
227+
// deprecated library
228+
'**/mui-joy/**/*',
229+
// used internally, not used on app router yet
230+
'**/mui-docs/**/*',
231+
],
232+
rules: {
233+
'mui/add-undef-to-optional': 'error',
234+
},
235+
},
236+
{
237+
files: [`packages/*/src/**/*${EXTENSION_TS}`],
224238
ignores: [
225239
'**/*.spec.*',
226240
'**/*.test.*',

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
"@mui-internal/api-docs-builder-core": "workspace:^",
9797
"@mui/internal-babel-plugin-minify-errors": "2.0.8-canary.20",
9898
"@mui/internal-bundle-size-checker": "1.0.9-canary.60",
99-
"@mui/internal-code-infra": "0.0.3-canary.87",
99+
"@mui/internal-code-infra": "0.0.3-canary.90",
100100
"@mui/internal-docs-utils": "workspace:^",
101101
"@mui/internal-netlify-cache": "0.0.2-canary.1",
102102
"@mui/internal-scripts": "workspace:^",

‎packages-internal/scripts/typescript-to-proptypes/src/getPropTypesFromFile.ts‎

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -412,21 +412,58 @@ function checkSymbol({
412412
// but not
413413
// { a?: React.ElementType, b: React.ReactElement }
414414
// get around this by not using the TypeChecker
415-
if (
416-
declaration &&
417-
ts.isPropertySignature(declaration) &&
418-
declaration.type &&
419-
ts.isTypeReferenceNode(declaration.type)
420-
) {
421-
const name = declaration.type.typeName.getText();
422-
if (
423-
name === 'React.ElementType' ||
424-
name === 'React.ComponentType' ||
425-
name === 'React.JSXElementConstructor' ||
426-
name === 'React.ReactElement'
427-
) {
415+
if (declaration && ts.isPropertySignature(declaration) && declaration.type) {
416+
// Helper to check if a type node is a React element type reference
417+
const getElementTypeName = (typeNode: ts.TypeNode): string | null => {
418+
if (ts.isTypeReferenceNode(typeNode)) {
419+
const name = typeNode.typeName.getText();
420+
if (
421+
name === 'React.ElementType' ||
422+
name === 'React.ComponentType' ||
423+
name === 'React.JSXElementConstructor' ||
424+
name === 'React.ReactElement'
425+
) {
426+
return name;
427+
}
428+
}
429+
return null;
430+
};
431+
432+
// Check for direct type reference (e.g., `prop: React.ElementType`)
433+
let elementTypeName = getElementTypeName(declaration.type);
434+
435+
// Also check for union types like `React.ElementType | undefined`
436+
// but NOT for unions with other types like `string | React.ReactElement | undefined`
437+
if (!elementTypeName && ts.isUnionTypeNode(declaration.type)) {
438+
let foundElementType: string | null = null;
439+
let hasOtherNonUndefinedTypes = false;
440+
441+
for (const typeNode of declaration.type.types) {
442+
const name = getElementTypeName(typeNode);
443+
if (name) {
444+
foundElementType = name;
445+
} else if (
446+
// Check if this is an undefined type (keyword or literal)
447+
!(
448+
typeNode.kind === ts.SyntaxKind.UndefinedKeyword ||
449+
(ts.isLiteralTypeNode(typeNode) &&
450+
typeNode.literal.kind === ts.SyntaxKind.UndefinedKeyword)
451+
)
452+
) {
453+
// Found a type that's neither an element type nor undefined
454+
hasOtherNonUndefinedTypes = true;
455+
}
456+
}
457+
458+
// Only use the element type if the union doesn't have other non-undefined types
459+
if (foundElementType && !hasOtherNonUndefinedTypes) {
460+
elementTypeName = foundElementType;
461+
}
462+
}
463+
464+
if (elementTypeName) {
428465
const elementNode = createElementType({
429-
elementType: name === 'React.ReactElement' ? 'element' : 'elementType',
466+
elementType: elementTypeName === 'React.ReactElement' ? 'element' : 'elementType',
430467
jsDoc,
431468
});
432469

‎packages/mui-lab/src/Masonry/Masonry.d.ts‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,38 +11,38 @@ export interface MasonryOwnProps {
1111
/**
1212
* Override or extend the styles applied to the component.
1313
*/
14-
classes?: Partial<MasonryClasses>;
14+
classes?: Partial<MasonryClasses> | undefined;
1515
/**
1616
* Number of columns.
1717
* @default 4
1818
*/
19-
columns?: ResponsiveStyleValue<number | string>;
19+
columns?: ResponsiveStyleValue<number | string> | undefined;
2020
/**
2121
* The default number of columns of the component. This is provided for server-side rendering.
2222
*/
23-
defaultColumns?: number;
23+
defaultColumns?: number | undefined;
2424
/**
2525
* The default height of the component in px. This is provided for server-side rendering.
2626
*/
27-
defaultHeight?: number;
27+
defaultHeight?: number | undefined;
2828
/**
2929
* The default spacing of the component. Like `spacing`, it is a factor of the theme's spacing. This is provided for server-side rendering.
3030
*/
31-
defaultSpacing?: number;
31+
defaultSpacing?: number | undefined;
3232
/**
3333
* Defines the space between children. It is a factor of the theme's spacing.
3434
* @default 1
3535
*/
36-
spacing?: ResponsiveStyleValue<number | string>;
36+
spacing?: ResponsiveStyleValue<number | string> | undefined;
3737
/**
3838
* Allows using sequential order rather than adding to shortest column
3939
* @default false
4040
*/
41-
sequential?: boolean;
41+
sequential?: boolean | undefined;
4242
/**
4343
* Allows defining system overrides as well as additional CSS styles.
4444
*/
45-
sx?: SxProps<Theme>;
45+
sx?: SxProps<Theme> | undefined;
4646
}
4747

4848
export interface MasonryTypeMap<

‎packages/mui-lab/src/TabPanel/TabPanel.d.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ export interface TabPanelProps extends StandardProps<React.HTMLAttributes<HTMLDi
1212
/**
1313
* Override or extend the styles applied to the component.
1414
*/
15-
classes?: Partial<TabPanelClasses>;
15+
classes?: Partial<TabPanelClasses> | undefined;
1616
/**
1717
* The system prop that allows defining system overrides as well as additional CSS styles.
1818
*/
19-
sx?: SxProps<Theme>;
19+
sx?: SxProps<Theme> | undefined;
2020
/**
2121
* The `value` of the corresponding `Tab`. Must use the index of the `Tab` when
2222
* no `value` was passed to `Tab`.
@@ -26,7 +26,7 @@ export interface TabPanelProps extends StandardProps<React.HTMLAttributes<HTMLDi
2626
* Always keep the children in the DOM.
2727
* @default false
2828
*/
29-
keepMounted?: boolean;
29+
keepMounted?: boolean | undefined;
3030
}
3131

3232
/**

‎packages/mui-lab/src/Timeline/Timeline.types.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,21 @@ export interface TimelineProps extends StandardProps<React.ComponentProps<'ul'>>
88
* The position where the TimelineContent should appear relative to the time axis.
99
* @default 'right'
1010
*/
11-
position?: 'left' | 'right' | 'alternate' | 'alternate-reverse';
11+
position?: 'left' | 'right' | 'alternate' | 'alternate-reverse' | undefined;
1212
/**
1313
* The content of the component.
1414
*/
1515
children?: React.ReactNode;
1616
/**
1717
* Override or extend the styles applied to the component.
1818
*/
19-
classes?: Partial<TimelineClasses>;
19+
classes?: Partial<TimelineClasses> | undefined;
2020
/**
2121
* className applied to the root element.
2222
*/
23-
className?: string;
23+
className?: string | undefined;
2424
/**
2525
* The system prop that allows defining system overrides as well as additional CSS styles.
2626
*/
27-
sx?: SxProps<Theme>;
27+
sx?: SxProps<Theme> | undefined;
2828
}

‎packages/mui-lab/src/TimelineConnector/TimelineConnector.d.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ export interface TimelineConnectorProps extends StandardProps<
1414
/**
1515
* Override or extend the styles applied to the component.
1616
*/
17-
classes?: Partial<TimelineConnectorClasses>;
17+
classes?: Partial<TimelineConnectorClasses> | undefined;
1818
/**
1919
* The system prop that allows defining system overrides as well as additional CSS styles.
2020
*/
21-
sx?: SxProps<Theme>;
21+
sx?: SxProps<Theme> | undefined;
2222
}
2323

2424
/**

‎packages/mui-lab/src/TimelineContent/TimelineContent.d.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ export interface TimelineContentProps extends StandardProps<TypographyProps> {
1313
/**
1414
* Override or extend the styles applied to the component.
1515
*/
16-
classes?: Partial<TimelineContentClasses>;
16+
classes?: Partial<TimelineContentClasses> | undefined;
1717
/**
1818
* The system prop that allows defining system overrides as well as additional CSS styles.
1919
*/
20-
sx?: SxProps<Theme>;
20+
sx?: SxProps<Theme> | undefined;
2121
}
2222

2323
/**

‎packages/mui-lab/src/TimelineDot/TimelineDot.d.ts‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,28 @@ export interface TimelineDotProps extends StandardProps<React.HTMLAttributes<HTM
1717
/**
1818
* Override or extend the styles applied to the component.
1919
*/
20-
classes?: Partial<TimelineDotClasses>;
20+
classes?: Partial<TimelineDotClasses> | undefined;
2121
/**
2222
* The dot can have a different colors.
2323
* @default 'grey'
2424
*/
25-
color?: OverridableStringUnion<
26-
'inherit' | 'grey' | 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning',
27-
TimelineDotPropsColorOverrides
28-
>;
25+
color?:
26+
| OverridableStringUnion<
27+
'inherit' | 'grey' | 'primary' | 'secondary' | 'error' | 'info' | 'success' | 'warning',
28+
TimelineDotPropsColorOverrides
29+
>
30+
| undefined;
2931
/**
3032
* The system prop that allows defining system overrides as well as additional CSS styles.
3133
*/
32-
sx?: SxProps<Theme>;
34+
sx?: SxProps<Theme> | undefined;
3335
/**
3436
* The dot can appear filled or outlined.
3537
* @default 'filled'
3638
*/
37-
variant?: OverridableStringUnion<'filled' | 'outlined', TimelineDotPropsVariantOverrides>;
39+
variant?:
40+
| OverridableStringUnion<'filled' | 'outlined', TimelineDotPropsVariantOverrides>
41+
| undefined;
3842
}
3943

4044
/**

‎packages/mui-lab/src/TimelineItem/TimelineItem.d.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ export interface TimelineItemProps extends StandardProps<React.HTMLAttributes<HT
88
/**
99
* The position where the timeline's item should appear.
1010
*/
11-
position?: 'left' | 'right' | 'alternate' | 'alternate-reverse';
11+
position?: 'left' | 'right' | 'alternate' | 'alternate-reverse' | undefined;
1212
/**
1313
* The content of the component.
1414
*/
1515
children?: React.ReactNode;
1616
/**
1717
* Override or extend the styles applied to the component.
1818
*/
19-
classes?: Partial<TimelineItemClasses>;
19+
classes?: Partial<TimelineItemClasses> | undefined;
2020
/**
2121
* The system prop that allows defining system overrides as well as additional CSS styles.
2222
*/
23-
sx?: SxProps<Theme>;
23+
sx?: SxProps<Theme> | undefined;
2424
}
2525

2626
/**

0 commit comments

Comments
 (0)