property x does not exist on type '(props?: any) => ClassNameMap<"x">'

580 Views Asked by At

I have to create the styles based on a param, for that i have done as below.

 const useStyles = (isLayoutReadOnly = false) =>
  makeStyles((theme: Theme) => {
    return {
      x: {
        margin: theme.spacing(0, 0, 1, 0),
          marginLeft: !isLayoutReadOnly ? '-20px' : undefined 
        }
      }
    };
  });

And i am trying to use it this way,

 const { x } = useStyles(isLayoutReadOnly);

Which throws me the error

property x does not exist on type '(props?: any) => ClassNameMap<"x">'

How should i fix this issue? I have tried setting the custom return types and also ReturnType<typeof makeStyles>, how ever, it is unable to detect.

1

There are 1 best solutions below

3
On BEST ANSWER

You are setting useStyles to a function that calls makeStyles:

const useStyles = (isLayoutReadOnly = false) => makeStyles()...

The example in the docs shows useStyles being set to makeStyles directly rather than to a function:

const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      backgroundColor: theme.palette.red,
    },
  }),
);

You can achieve the same pattern with your code by using an Immediately Invoked Function Expression. By wrapping your function in (() => {}) parenthesis and then adding () parenthesis at the end, you can call your function immediately to make sure useStyles gets the return value of your (isLayoutReadOnly) => ... function. Here's how that would look:

  const useStyles = ((isLayoutReadOnly = false) =>
  makeStyles((theme) => {
    return {
      x: {
        margin: theme.spacing(0, 0, 1, 0),
          marginLeft: !isLayoutReadOnly ? '-20px' : undefined 
        }
      }
  }))(isLayoutReadOnly);

The other option is to adjust how you are calling useStyles. You can add an additional set of parenthesis to your call to useStyles to call the function that is returned to get the expected behavior:

  const  {x}  = useStyles(isLayoutReadOnly)();