-
-
Notifications
You must be signed in to change notification settings - Fork 32.6k
[styled-engine] Fix style overrides variants type #45478
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
[styled-engine] Fix style overrides variants type #45478
Conversation
Netlify deploy previewhttps://deploy-preview-45478--material-ui.netlify.app/ Bundle size report |
@@ -42,7 +42,7 @@ const items = [ | |||
const Chip = styled(MuiChip)(({ theme }) => ({ | |||
variants: [ | |||
{ | |||
props: ({ selected }) => selected, | |||
props: ({ selected }) => !!selected, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have to fix this because the type of selected
is boolean | undefined
.
Should we loosen the type like of props? to be () => boolean | null | undefined
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mind the !!
to cast into boolean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean this is a breaking change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue it's a fix as it was always supposed to be () => boolean
(it's only boolean
in the CSSObjectWithVariants
type), but it wasn't actually because the type wasn't being correctly picked up.
It's one of those fixes that could be perceived as a breaking change.
Maybe we could compromise with a minor release and an explanation on the changelog?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would be the last thing that we need to decide on. Similar to the styles
now being required, this is a fix that might be perceived as breaking.
My proposal is that we release it with in a minor version and a note.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My proposal is that we release it with in a minor version and a note.
Let's do that.
| ComponentSelector | ||
| Keyframes | ||
| SerializedStyles | ||
| CSSPropertiesWithMultiValues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a myth to me. If not adding CSSPropertiesWithMultiValues
explicitly as a union, the spec fail for recreating nested theme.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you mean with "myth"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At first, I thought that CSSObject
is enough because it extends CSSPropertiesWithMultiValues
. However, if I excluded CSSPropertiesWithMultiValues
from the union type, I got this error from createTheme.spec
:

Here is the full error:
Argument of type 'Theme' is not assignable to parameter of type 'Omit<ThemeOptions, "components"> & Pick<CssVarsThemeOptions, "colorSchemes" | "defaultColorScheme" | "components"> & { ...; }'.
Type 'Theme' is not assignable to type 'Pick<CssVarsThemeOptions, "colorSchemes" | "defaultColorScheme" | "components">'.
Types of property 'components' are incompatible.
Type 'Components<BaseTheme> | undefined' is not assignable to type 'Components<Omit<Theme, "palette" | "components"> & CssVarsTheme> | undefined'.
Type 'Components<BaseTheme>' is not assignable to type 'Components<Omit<Theme, "palette" | "components"> & CssVarsTheme>'.
Types of property 'MuiAlert' are incompatible.
Type '{ defaultProps?: Partial<AlertProps> | undefined; styleOverrides?: Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", BaseTheme>> | undefined; variants?: { ...; }[] | undefined; } | undefined' is not assignable to type '{ defaultProps?: Partial<AlertProps> | undefined; styleOverrides?: Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", Omit<Theme, "palette" | "components"> & CssVarsTheme>> | undefined; variants?: { ...; }[] | undefined; } | undefined'.
Type '{ defaultProps?: Partial<AlertProps> | undefined; styleOverrides?: Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", BaseTheme>> | undefined; variants?: { ...; }[] | undefined; }' is not assignable to type '{ defaultProps?: Partial<AlertProps> | undefined; styleOverrides?: Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", Omit<Theme, "palette" | "components"> & CssVarsTheme>> | undefined; variants?: { ...; }[] | undefined; }'.
Types of property 'styleOverrides' are incompatible.
Type 'Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", BaseTheme>> | undefined' is not assignable to type 'Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", Omit<Theme, "palette" | "components"> & CssVarsTheme>> | undefined'.
Type 'Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", BaseTheme>>' is not assignable to type 'Partial<OverridesStyleRules<keyof AlertClasses, "MuiAlert", Omit<Theme, "palette" | "components"> & CssVarsTheme>>'.
Types of property 'root' are incompatible.
Type 'Interpolation<AlertProps & Record<string, unknown> & { ownerState: AlertProps & Record<string, unknown>; } & { theme: BaseTheme; }>' is not assignable to type 'Interpolation<AlertProps & Record<string, unknown> & { ownerState: AlertProps & Record<string, unknown>; } & { theme: Omit<Theme, "palette" | "components"> & CssVarsTheme; }>'.
Type 'CSSObject & { variants?: { props: Partial<AlertProps & Record<string, unknown> & { ownerState: AlertProps & Record<string, unknown>; } & { ...; }> | ((props: Partial<...> & { ...; }) => boolean); style: CSSObject | ((args: { ...; }) => CSSObject); }[] | undefined; }' is not assignable to type 'Interpolation<AlertProps & Record<string, unknown> & { ownerState: AlertProps & Record<string, unknown>; } & { theme: Omit<Theme, "palette" | "components"> & CssVarsTheme; }>'.
Type 'CSSObject & { variants?: { props: Partial<AlertProps & Record<string, unknown> & { ownerState: AlertProps & Record<string, unknown>; } & { ...; }> | ((props: Partial<...> & { ...; }) => boolean); style: CSSObject | ((args: { ...; }) => CSSObject); }[] | undefined; }' is not assignable to type 'Keyframes'.
Type 'CSSObject & { variants?: { props: Partial<AlertProps & Record<string, unknown> & { ownerState: AlertProps & Record<string, unknown>; } & { ...; }> | ((props: Partial<...> & { ...; }) => boolean); style: CSSObject | ((args: { ...; }) => CSSObject); }[] | undefined; }' is missing the following properties from type '{ name: string; styles: string; anim: number; toString: () => string; }': name, styles, animts(2345)
I don't fully understand why.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error is not related too much to the type that's being added, this is suspicious, let me check it again locally and I will report back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on this type: https://github.com/mui/material-ui/blob/master/packages/mui-material/src/styles/createTheme.ts#L38 the error is expected in my opinion. The issue is that in createTheme, we return this type: https://github.com/mui/material-ui/blob/master/packages/mui-material/src/styles/createThemeNoVars.d.ts#L82 which has different definition for components
than the input of createTheme
. We should probably loosen the input type for createTheme
, to accept a Theme
, if we are allowing this use-case. We should also make sure that all proposed options from https://mui.com/material-ui/customization/theming/#nesting-the-theme are type safe.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed loosening createTheme
's input type in the past, let's try it out @siriwatknp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DiegoAndai I tried loosen the type and include the Theme
but it produces bigger errors in the existing spec files.
At this point, I think having the CSSPropertiesWithMultiValues
without loosen the type might be the safest in my opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this change is causing major issues on mui-x styled
usages with callback props
:
mui/mui-x#17802
@siriwatknp, could you check if there is some oversight in the type? 🙏
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I am taking a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote the info in slack > https://mui-org.slack.com/archives/C011VC970AW/p1747795216756729
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for taking a look at this @siriwatknp! 😊
I have a couple of questions
Hey @siriwatknp! I took a look at this, and I managed to remove The
|
I suggest not removing it as it will introduce another issue for people who read const theme = createTheme({
component: { … }
})
console.log(theme.components); // << TS error. Also, removing the |
…esWithMultiValues" This reverts commit daa9579.
@siriwatknp I closed #45346 in favor of this PR, lets move forward with this solution @mnajdova may I ask you to review this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will report soon with my findings.
@@ -42,7 +42,7 @@ const items = [ | |||
const Chip = styled(MuiChip)(({ theme }) => ({ | |||
variants: [ | |||
{ | |||
props: ({ selected }) => selected, | |||
props: ({ selected }) => !!selected, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean this is a breaking change?
@@ -218,6 +218,7 @@ const theme = createTheme(); | |||
variants: [ | |||
{ | |||
props: ({ ownerState }) => ownerState.color === 'primary', | |||
style: {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't style required before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was, but the CSSObjectWithVariants
wasn't being picked correctly, so it wasn't enforced. Is that correct @siriwatknp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. that's correct.
| ComponentSelector | ||
| Keyframes | ||
| SerializedStyles | ||
| CSSPropertiesWithMultiValues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error is not related too much to the type that's being added, this is suspicious, let me check it again locally and I will report back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, let's release the fix.
@mnajdova FYI:
- There are some type changes that might be perceived as "breaking":
- Variants'
props
is now correctly typed as() => boolean
- Variants'
styles
is now correctly required
- Variants'
These were always the intended types, but they weren't being used, which is the bug we're fixing now. Because they're now correctly used, this effectively changed the resolved types.
Because these are the correct types, Jun and I think this is a fix worth releasing in v7. But because it can be perceived as breaking, the compromise is to release it in a minor bump and explain it in the CHANGELOG. Adapting to these changes is straightforward.
In the worst case scenario, if too many users complain, plan B is to loosen these types in a patch version after the minor one.
Closes #45275
The issue is that
Omit<CSSOthersObject, 'variants'>
doesn't work as expected asCSSOthersObject
is a mapped type, whichOmit
has known issues with:In a nutshell: By design,
Omit
won't remove variants fromCSSOthersObject
, so the type defined inCSSObjectWithVariants
is not used.Solution and discussion below