Skip to content

Conversation

siriwatknp
Copy link
Member

@siriwatknp siriwatknp commented Oct 2, 2025

Important

Breaking Change: Deprecated type exports moved from @mui/material/styles to @mui/material/stylesDeprecated

Components, ComponentsProps, ComponentsOverrides, ComponentsVariants, adaptV4Theme, or related types from @mui/material/styles, moved to @mui/material/stylesDeprecated.

🎯 Main Purpose

Fix a severe TypeScript performance issue caused by circular type dependencies in the ThemeOptions and Theme types.
Components imports all of components types from the library, causing massive type instantiation when createTheme() is used.

🔍 Problem & Solution Context

  • Deprecate Components type that import all components types and replace it with an empty interface ThemeComponents (user will need to augment this interface for autocompletion)
  • Deprecate adaptV4Theme from styles folder as it relying on the Components.
  • Introduce CreateThemeComponent utility type for declaring component theme type
  • Export component theme type from each component so that users can augment the ThemeComponents with built-in component theme type.

With this change, perf improvement ~50% (see the result at the bottom)

🔧 Key Changes

Type System Overhaul

  • Replaced circular generic: Changed Components<Omit<Theme, 'components'>> to simple ThemeComponents interface in createThemeFoundation.ts:36
  • New type helper: Added CreateThemeComponent<SlotNames, Props, OwnerState> in createThemeNoVars.d.ts:98 for component-specific theme customization
  • Example pattern: Button component now exports ButtonTheme type in Button.d.ts:149 showing how other components should define their theme types

Breaking Changes

  • Moved deprecated types: All legacy component types (Components, ComponentsProps, ComponentsOverrides, etc.) moved from styles/ to new stylesDeprecated/ folder
  • Updated exports: Removed deprecated type exports from styles/index.d.ts:84 - users must now import from @mui/material/stylesDeprecated
  • Removed adaptV4Theme: No longer exported from main styles entry point (available in deprecated path)

Migration

Recommended: selective theme components to optimize TypeScript

import type { ButtonTheme } from "@mui/material/Button";
import type { AccordionTheme } from "@mui/material/Button";

declare module "@mui/material/styles" {
  interface ThemeComponents extends ButtonTheme, AccordionTheme {}
}

Preserve existing behavior: extend the ThemeComponents with the deprecated Components

import type { Components } from "@mui/material/stylesDeprecated";

declare module "@mui/material/styles" {
  interface ThemeComponents extends Components {}
}

Material UI as dependency (e.g. MUI X)

Update the themeAugmentation.ts to augment the @mui/material/stylesDeprecated

// packages/x-data-grid/src/themeAugmentation/props.ts
// declare both for backward compatibility
declare module '@mui/material/styles' {
  interface ComponentsPropsList extends DataGridComponentsPropsList {}
  interface Components<Theme = unknown> extends DataGridComponents<Theme> {}
}
declare module '@mui/material/stylesDeprecated' {
  interface ComponentsPropsList extends DataGridComponentsPropsList {}
  interface Components<Theme = unknown> extends DataGridComponents<Theme> {}
}

Backward Compatibility

  • Created stylesDeprecated module: New folder with all legacy types maintained for backward compatibility
  • Updated MUI Lab: All mui-lab/src/themeAugmentation/* files now import from and augment the deprecated module
  • Migration path: Existing code can continue working by updating imports to stylesDeprecated

Performance Testing Infrastructure

  • New perf-test folder: Added packages/mui-material/perf-test/ with tooling to measure TypeScript performance
  • Test case: test-createTheme.ts:1 demonstrates the new pattern and allows measuring type instantiation costs
  • Documentation: README.md:1 provides comprehensive guide on running TypeScript diagnostics

📁 Important Files to Review

  • packages/mui-material/src/styles/createThemeNoVars.d.ts:42 - Core type system changes that break the circular dependency. Review the simplified ThemeComponents type and new CreateThemeComponent helper.

  • packages/mui-material/src/styles/createThemeFoundation.ts:36 - New ThemeComponents interface definition. Verify this simple interface provides sufficient flexibility.

  • packages/mui-material/src/stylesDeprecated/ - All deprecated types moved here. Critical for ensuring backward compatibility works correctly, especially the module augmentation pattern.

  • packages/mui-lab/src/themeAugmentation/components.ts:5 - Updated to import from deprecated path and augment stylesDeprecated module instead of styles. Validates the backward compatibility strategy.

📋 Complete File Changes

Core Type System:

  • src/styles/createTheme.ts - Added exports for new types
  • src/styles/createThemeFoundation.ts - Added ThemeComponents interface
  • src/styles/createThemeNoVars.d.ts - Replaced circular type, added CreateThemeComponent
  • src/styles/createThemeWithVars.d.ts - Removed redundant components override
  • src/styles/useThemeProps.d.ts - Updated to use ThemeComponents
  • src/styles/index.d.ts - Removed deprecated exports, added new type exports
  • src/styles/index.js - Removed adaptV4Theme export

Deprecated Types (moved to stylesDeprecated/):

  • adaptV4Theme.d.ts, adaptV4Theme.js, adaptV4Theme.test.js
  • components.ts, overrides.ts, props.ts, variants.ts
  • index.ts (new) - Re-exports all deprecated types

Component Updates:

  • src/Button/Button.d.ts - Added ButtonTheme export as example pattern
  • src/DefaultPropsProvider/DefaultPropsProvider.tsx - Updated import path
  • src/locale/utils/LocaleTextApi.ts - Updated import path

MUI Lab Updates:

  • mui-lab/src/themeAugmentation/components.ts - Import from deprecated path
  • mui-lab/src/themeAugmentation/overrides.ts - Import from deprecated path
  • mui-lab/src/themeAugmentation/props.ts - Import from deprecated path

Documentation Theme:

  • mui-docs/src/branding/brandingTheme.ts - Extends ThemeComponents with deprecated Components<Theme>

Performance Testing:

  • perf-test/README.md - Guide for running TypeScript performance diagnostics
  • perf-test/test-createTheme.ts - Test case for measuring type instantiation
  • perf-test/tsconfig.json - TypeScript configuration for perf testing

🚀 Impact

Performance Improvements:

  • Significantly reduces TypeScript type instantiations (targeting < 500,000)
  • Lowers memory usage during type-checking (targeting < 300MB)
  • Faster IDE autocomplete and type-checking for theme customization

Developer Experience:

  • Components can now export their own theme types for better autocomplete
  • Cleaner, more explicit type definitions
  • Performance testing infrastructure helps prevent future regressions

Migration Required:

  • Projects importing deprecated types from @mui/material/styles need to update imports to @mui/material/stylesDeprecated
  • MUI Lab already updated and compatible with the new system
  • New projects should use the CreateThemeComponent pattern for component customization

💡 Implementation Notes

The key insight here is separating concerns: instead of having one massive recursive generic type that handles all components, each component can define its own theme type using the CreateThemeComponent helper. This makes TypeScript's job much easier since it doesn't have to recursively expand a generic type for every component.

The ButtonTheme example shows the pattern:

export type ButtonTheme = {
  MuiButton: CreateThemeComponent<ButtonClassKey, ButtonProps>;
};

// Usage:
declare module '@mui/material/styles' {
  interface ThemeComponents extends ButtonTheme {}
}

This pattern scales linearly rather than exponentially, which is why it's so much more performant.

Note

The perf-test folder provides tooling to measure the impact of these changes. Run npx tsc --diagnostics in that folder to see type instantiation counts and memory usage.

Result

Metric Baseline (ThemeOptions) Fix Improvement
Instantiations 747348 337500 54.9%
Memory used 553 MB 364879K 34.0%
Check time 4.43s 2.38s 46.3%
Total time 5.65s 3.29s 41.7%

Before:

Files:              815
Lines:           164674
Identifiers:     130208
Symbols:         377356
Types:           117528
Instantiations:  747348
Memory used:    553221K
I/O read:         0.15s
I/O write:        0.00s
Parse time:       1.02s
Bind time:        0.20s
Check time:       4.43s
Emit time:        0.00s
Total time:       5.65s

After:

Files:              355
Lines:           139531
Identifiers:     110988
Symbols:         258356
Types:            92894
Instantiations:  337500
Memory used:    364879K
I/O read:         0.08s
I/O write:        0.00s
Parse time:       0.73s
Bind time:        0.18s
Check time:       2.38s
Emit time:        0.00s
Total time:       3.29s

Test

Follow the packages/mui-material/perf-test/README.md to test this PR.


@siriwatknp siriwatknp added performance breaking change Introduces changes that are not backward compatible. typescript package: material-ui Specific to Material UI. labels Oct 2, 2025
@mui-bot
Copy link

mui-bot commented Oct 2, 2025

Netlify deploy preview

https://deploy-preview-47013--material-ui.netlify.app/

Bundle size report

Bundle Parsed size Gzip size
@mui/material ▼-906B(-0.17%) ▼-253B(-0.17%)
@mui/lab 0B(0.00%) 0B(0.00%)
@mui/system 0B(0.00%) 0B(0.00%)
@mui/utils 0B(0.00%) 0B(0.00%)

Details of bundle changes

Generated by 🚫 dangerJS against b32cbb7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change Introduces changes that are not backward compatible. package: material-ui Specific to Material UI. performance typescript
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants