garronej / tss-react

✨ Dynamic CSS-in-TS solution, based on Emotion
https://tss-react.dev
MIT License
608 stars 37 forks source link

Typedefiniton problem when we use mixins #131

Open hugo4711 opened 1 year ago

hugo4711 commented 1 year ago

We are getting obscure typescript errors when using mixins and we have no idea how to fix this:

Please see the following code, where we mix in theme.mixins.toolbar

const useStyles = makeStyles({ name: 'MaraMenu' })((theme) => ({
  root: {
    paddingBottom: theme.spacing(2)
  },
  drawer: {
    [theme.breakpoints.up('md')]: {
      width: drawerWidth,
      flexShrink: 0
    }
  },
  toolbar: theme.mixins.toolbar,
  drawerPaper: {
    width: drawerWidth,
    overflowY: 'visible',
    background: theme.palette.background.default
  },
  menu: {
    overflowY: 'auto',
    height: '80vh',
    padding: theme.spacing(1)
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing(3)
  },
  uncommittedChangesButton: {
    margin: theme.spacing(2, 0, 2, 6),
    marginLeft: '10%'
  }
}))

This gives the following error:

TS2345: Argument of type '(theme: Theme) => { root: { paddingBottom: string; }; drawer: { [x: string]: { width: number; flexShrink: number; }; }; toolbar: CSSProperties; drawerPaper: { width: number; overflowY: "visible"; background: string; }; menu: { ...; }; content: { ...; }; uncommittedChangesButton: { ...; }; }' is not assignable to parameter of type 'Record<"root" | "content" | "drawer" | "toolbar" | "drawerPaper" | "menu" | "uncommittedChangesButton", CSSObject> | ((theme: Theme, params: void, classes: Record<...>) => Record<...>)'.   Type '(theme: Theme) => { root: { paddingBottom: string; }; drawer: { [x: string]: { width: number; flexShrink: number; }; }; toolbar: CSSProperties; drawerPaper: { width: number; overflowY: "visible"; background: string; }; menu: { ...; }; content: { ...; }; uncommittedChangesButton: { ...; }; }' is not assignable to type '(theme: Theme, params: void, classes: Record<never, string>) => Record<"root" | "content" | "drawer" | "toolbar" | "drawerPaper" | "menu" | "uncommittedChangesButton", CSSObject>'.     Call signature return types '{ root: { paddingBottom: string; }; drawer: { [x: string]: { width: number; flexShrink: number; }; }; toolbar: CSSProperties; drawerPaper: { width: number; overflowY: "visible"; background: string; }; menu: { ...; }; content: { ...; }; uncommittedChangesButton: { ...; }; }' and 'Record<"root" | "content" | "drawer" | "toolbar" | "drawerPaper" | "menu" | "uncommittedChangesButton", CSSObject>' are incompatible.       The types of 'toolbar.appearance' are incompatible between these types.         Type 'Appearance | undefined' is not assignable to type 'Appearance | Appearance[] | undefined'.           Type '"revert-layer"' is not assignable to type 'Appearance | Appearance[] | undefined'.
garronej commented 1 year ago

Hi @hugo4711,

I read:

Type '"revert-layer"' is not assignable to type 'Appearance | Appearance[] | undefined'.

But in the current version of csstype, "revert-layer" is assignable to Appearance.

image

I think you should try reinstalling your dependencies (delete your package.lock?) , if it still doesn't work because some library that you use depend on an older version of css type you can safely pin csstype to a newer version (assuming you use yarn):

    "resolutions": {
        "csstype": "3.1.1"
    },

Let me know if it fixes the issue

mdismer commented 1 year ago

We have tried adding the resolution for cssytpes unfortunately this leads to a different error:

Argument of type '(theme: Theme) => { root: { paddingBottom: string; }; drawer: { [x: string]: { width: number; flexShrink: number; }; }; toolbar: CSSProperties; drawerPaper: { width: number; overflowY: "visible"; background: string; }; menu: { ...; }; content: { ...; }; uncommittedChangesButton: { ...; }; }' is not assignable to parameter of type 'Record<"root" | "content" | "drawer" | "toolbar" | "drawerPaper" | "menu" | "uncommittedChangesButton", CSSObject> | ((theme: Theme, params: void, classes: Record<...>) => Record<...>)'.   Type '(theme: Theme) => { root: { paddingBottom: string; }; drawer: { [x: string]: { width: number; flexShrink: number; }; }; toolbar: CSSProperties; drawerPaper: { width: number; overflowY: "visible"; background: string; }; menu: { ...; }; content: { ...; }; uncommittedChangesButton: { ...; }; }' is not assignable to type '(theme: Theme, params: void, classes: Record<never, string>) => Record<"root" | "content" | "drawer" | "toolbar" | "drawerPaper" | "menu" | "uncommittedChangesButton", CSSObject>'.     Call signature return types '{ root: { paddingBottom: string; }; drawer: { [x: string]: { width: number; flexShrink: number; }; }; toolbar: CSSProperties; drawerPaper: { width: number; overflowY: "visible"; background: string; }; menu: { ...; }; content: { ...; }; uncommittedChangesButton: { ...; }; }' and 'Record<"root" | "content" | "drawer" | "toolbar" | "drawerPaper" | "menu" | "uncommittedChangesButton", CSSObject>' are incompatible.       The types of 'toolbar' are incompatible between these types.         Type 'CSSProperties' is not assignable to type 'CSSObject'.           'string' index signatures are incompatible.             Type 'unknown' is not assignable to type 'CSSInterpolation'.
garronej commented 1 year ago

I'm sorry, this error is annoying indeed but the problem comes from MUI:

Type 'CSSProperties (as defined in @mui/material/styles/createMixins.d.ts') is not assignable to type 'CSSObject (as defined in csstype/index.d.ts)'.           
Type 'unknown' is not assignable to type 'CSSInterpolation'.
image

If the type definition was:

image

It would fix the error:

image

@mnajdova would you be open to a PR that changes this type definition from interface inheritance to type intersection? I am not sure of the consequences it would have...

@mdismer I'm sorry but for now all I can suggest is:

- toolbar: theme.mixins.toolbar
+ toolbar: theme.mixins.toolbar as any

Best regards