Repository: mui/material-ui (TypeScript)
Date: 2024-05-27 05:23:53+00:00
Task type: Bug Fix

Issue:
responsiveFontSizes crashes when one of the variants is disabled
### Steps to reproduce

Link to live example:
https://stackblitz.com/edit/github-o8g8fe?file=src%2FApp.tsx

Steps:
1. Create a theme
2. Mark one of the default typography variants as undefined
3. use responsiveFontSizes on the theme


### Current behavior

When using the responsiveFontSizes on a theme where a default typography variant is disabled, the function crashs

### Expected behavior

responsiveFontSizes should just ignore disabled variants and not crash

### Context

I created a custom theme, with custom typography variants and disabled the default ones by marking them as undefined in the createTheme. and used the responsiveFontSizes to make the new variants as responsive, and it crashed

### Your environment

<details>
  <summary><code>npx @mui/envinfo</code></summary>

```
  Don't forget to mention which browser you used.
   System:
    OS: Windows 11 10.0.22635
  Binaries:
    Node: 18.20.2 - C:\Program Files\nodejs\node.EXE
    npm: 10.5.0 - C:\Program Files\nodejs\npm.CMD
    pnpm: Not Found
  Browsers:
    Chrome: 124.0.6367.203
  npmPackages:
    @emotion/react: ^11.11.3 => 11.11.4
    @emotion/styled: ^11.11.0 => 11.11.5
    @mui/base:  5.0.0-beta.40
    @mui/core-downloads-tracker:  5.15.17
    @mui/icons-material: ^5.15.4 => 5.15.17
    @mui/material:  5.15.17
    @mui/private-theming:  5.15.14
    @mui/styled-engine:  5.15.14
    @mui/system:  5.15.15
    @mui/types:  7.2.14
    @mui/utils:  5.15.14
    @mui/x-data-grid:  6.19.11
    @mui/x-date-pickers:  6.19.9
    @types/react:  18.3.2
    react:  18.3.1
    react-dom:  18.3.1
    typescript: ^5.3.3 => 5.4.5
```
</details>


**Search keywords**: responsiveFontSizes, crash


Issue discussion:
This is to be expected since we spread those variant definitions in a lot of places and there are no `undefined` checks. You could instead try to make them as empty object (`{}`) instead of undefined and see if that works.
But this way I cant have the type as undefined in Typescript, right? and so this variants will still show up in the typography as valid options, right?
Also, just for completeness, the documentation says to use "undefined" to disable a variant: https://mui.com/material-ui/customization/typography/#adding-amp-disabling-variants

> so this variants will still show up in the typography as valid options, right?

That is true. We'll need to handle `undefined` case in the library code.

Solution patch:
diff --git a/packages/mui-material/src/styles/responsiveFontSizes.js b/packages/mui-material/src/styles/responsiveFontSizes.js
--- a/packages/mui-material/src/styles/responsiveFontSizes.js
+++ b/packages/mui-material/src/styles/responsiveFontSizes.js
@@ -34,6 +34,11 @@ export default function responsiveFontSizes(themeInput, options = {}) {
 
   variants.forEach((variant) => {
     const style = typography[variant];
+
+    if (!style) {
+      return;
+    }
+
     const remFontSize = parseFloat(convert(style.fontSize, 'rem'));
 
     if (remFontSize <= 1) {


Test patch:
diff --git a/packages/mui-material/src/styles/responsiveFontSizes.test.js b/packages/mui-material/src/styles/responsiveFontSizes.test.js
--- a/packages/mui-material/src/styles/responsiveFontSizes.test.js
+++ b/packages/mui-material/src/styles/responsiveFontSizes.test.js
@@ -59,6 +59,19 @@ describe('responsiveFontSizes', () => {
     });
   });
 
+  it('should handle variants that have been reset to undefined', () => {
+    const theme = createTheme({
+      typography: {
+        h1: undefined,
+      },
+    });
+    const { typography } = responsiveFontSizes(theme, {
+      disableAlign: true,
+    });
+
+    expect(typography.h1).to.deep.equal(undefined);
+  });
+
   describe('when requesting a responsive typography with non unitless line height and alignment', () => {
     it('should throw an error, as this is not supported', () => {
       const theme = createTheme({